diff --git a/src/cache.cc b/src/cache.cc index 15e858d2..daca8bdb 100644 --- a/src/cache.cc +++ b/src/cache.cc @@ -1,8 +1,9 @@ #include "cache.h" #include "indexer.h" -#include "platform.h" #include "language_server_api.h" +#include "platform.h" + #include @@ -43,15 +44,15 @@ optional LoadCachedFileContents(Config* config, return ReadContent(GetCachedBaseFileName(config->cacheDirectory, filename)); } -void WriteToCache(Config* config, - IndexFile& file) { +void WriteToCache(Config* config, IndexFile& file) { if (!config->enableCacheWrite) return; std::string cache_basename = GetCachedBaseFileName(config->cacheDirectory, file.path); - LOG_IF_S(ERROR, file.file_contents_.empty()) << "Writing " << file.path << " to cache but it has no contents"; + LOG_IF_S(ERROR, file.file_contents_.empty()) + << "Writing " << file.path << " to cache but it has no contents"; assert(!file.file_contents_.empty()); std::ofstream cache_content; diff --git a/src/cache.h b/src/cache.h index 34f2da54..2296b2cf 100644 --- a/src/cache.h +++ b/src/cache.h @@ -4,8 +4,8 @@ #include #include -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; struct Config; struct IndexFile; @@ -16,5 +16,4 @@ std::unique_ptr LoadCachedIndex(Config* config, optional LoadCachedFileContents(Config* config, const std::string& filename); -void WriteToCache(Config* config, - IndexFile& file); \ No newline at end of file +void WriteToCache(Config* config, IndexFile& file); \ No newline at end of file diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 534d82b7..4a861a11 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -15,7 +15,6 @@ #include */ - namespace { #if false @@ -45,34 +44,37 @@ void EmitBacktrace() { unsigned Flags() { // TODO: use clang_defaultEditingTranslationUnitOptions()? - return - CXTranslationUnit_Incomplete | - CXTranslationUnit_KeepGoing | - CXTranslationUnit_CacheCompletionResults | - CXTranslationUnit_PrecompiledPreamble | - CXTranslationUnit_IncludeBriefCommentsInCodeCompletion + return CXTranslationUnit_Incomplete | CXTranslationUnit_KeepGoing | + CXTranslationUnit_CacheCompletionResults | + CXTranslationUnit_PrecompiledPreamble | + CXTranslationUnit_IncludeBriefCommentsInCodeCompletion #if !defined(_WIN32) - // For whatever reason, CreatePreambleOnFirstParse causes clang to become - // very crashy on windows. - // TODO: do more investigation, submit fixes to clang. - | CXTranslationUnit_CreatePreambleOnFirstParse + // For whatever reason, CreatePreambleOnFirstParse causes clang to + // become very crashy on windows. + // TODO: do more investigation, submit fixes to clang. + | CXTranslationUnit_CreatePreambleOnFirstParse #endif - ; + ; } -int GetCompletionPriority(const CXCompletionString& str, CXCursorKind result_kind, const std::string& label) { +int GetCompletionPriority(const CXCompletionString& str, + CXCursorKind result_kind, + const std::string& label) { int priority = clang_getCompletionPriority(str); if (result_kind == CXCursor_Destructor) { priority *= 100; - //std::cerr << "Bumping[destructor] " << ls_completion_item.label << std::endl; + // std::cerr << "Bumping[destructor] " << ls_completion_item.label << + // std::endl; } if (result_kind == CXCursor_ConversionFunction || - (result_kind == CXCursor_CXXMethod && StartsWith(label, "operator"))) { - //std::cerr << "Bumping[conversion] " << ls_completion_item.label << std::endl; + (result_kind == CXCursor_CXXMethod && StartsWith(label, "operator"))) { + // std::cerr << "Bumping[conversion] " << ls_completion_item.label << + // std::endl; priority *= 100; } if (clang_getCompletionAvailability(str) != CXAvailability_Available) { - //std::cerr << "Bumping[notavailable] " << ls_completion_item.label << std::endl; + // std::cerr << "Bumping[notavailable] " << ls_completion_item.label << + // std::endl; priority *= 100; } return priority; @@ -97,7 +99,6 @@ bool IsCallKind(CXCursorKind kind) { lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) { switch (cursor_kind) { - case CXCursor_ObjCInstanceMethodDecl: case CXCursor_CXXMethod: return lsCompletionItemKind::Method; @@ -146,128 +147,139 @@ lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) { case CXCursor_TypeRef: return lsCompletionItemKind::Reference; - //return lsCompletionItemKind::Property; - //return lsCompletionItemKind::Unit; - //return lsCompletionItemKind::Value; - //return lsCompletionItemKind::Keyword; - //return lsCompletionItemKind::Snippet; - //return lsCompletionItemKind::Color; - //return lsCompletionItemKind::File; + // return lsCompletionItemKind::Property; + // return lsCompletionItemKind::Unit; + // return lsCompletionItemKind::Value; + // return lsCompletionItemKind::Keyword; + // return lsCompletionItemKind::Snippet; + // return lsCompletionItemKind::Color; + // return lsCompletionItemKind::File; case CXCursor_NotImplemented: return lsCompletionItemKind::Text; default: - std::cerr << "[complete] Unhandled completion kind " << cursor_kind << std::endl; + std::cerr << "[complete] Unhandled completion kind " << cursor_kind + << std::endl; return lsCompletionItemKind::Text; } } -void BuildDetailString(CXCompletionString completion_string, std::string& label, std::string& detail, std::string& insert, std::vector* parameters) { +void BuildDetailString(CXCompletionString completion_string, + std::string& label, + std::string& detail, + std::string& insert, + std::vector* parameters) { int num_chunks = clang_getNumCompletionChunks(completion_string); for (int i = 0; i < num_chunks; ++i) { - CXCompletionChunkKind kind = clang_getCompletionChunkKind(completion_string, i); + CXCompletionChunkKind kind = + clang_getCompletionChunkKind(completion_string, i); switch (kind) { - case CXCompletionChunk_Optional: { - CXCompletionString nested = clang_getCompletionChunkCompletionString(completion_string, i); - BuildDetailString(nested, label, detail, insert, parameters); - break; - } + case CXCompletionChunk_Optional: { + CXCompletionString nested = + clang_getCompletionChunkCompletionString(completion_string, i); + BuildDetailString(nested, label, detail, insert, parameters); + break; + } - case CXCompletionChunk_Placeholder: { - std::string text = clang::ToString(clang_getCompletionChunkText(completion_string, i)); - parameters->push_back(text); - detail += text; - insert += "${" + std::to_string(parameters->size()) + ":" + text + "}"; - break; - } + case CXCompletionChunk_Placeholder: { + std::string text = + clang::ToString(clang_getCompletionChunkText(completion_string, i)); + parameters->push_back(text); + detail += text; + insert += "${" + std::to_string(parameters->size()) + ":" + text + "}"; + break; + } - case CXCompletionChunk_CurrentParameter: - // We have our own parsing logic for active parameter. This doesn't seem - // to be very reliable. - 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 = clang::ToString(clang_getCompletionChunkText(completion_string, i)); - label = text; - detail += text; - insert += text; - break; - } + case CXCompletionChunk_TypedText: { + std::string text = + clang::ToString(clang_getCompletionChunkText(completion_string, i)); + label = text; + detail += text; + insert += text; + break; + } - case CXCompletionChunk_Text: { - std::string text = clang::ToString(clang_getCompletionChunkText(completion_string, i)); - detail += text; - insert += text; - break; - } + case CXCompletionChunk_Text: { + std::string text = + clang::ToString(clang_getCompletionChunkText(completion_string, i)); + detail += text; + insert += text; + break; + } - case CXCompletionChunk_Informative: { - detail += clang::ToString(clang_getCompletionChunkText(completion_string, i)); - break; - } + case CXCompletionChunk_Informative: { + detail += + clang::ToString(clang_getCompletionChunkText(completion_string, i)); + break; + } - case CXCompletionChunk_ResultType: { - CXString text = clang_getCompletionChunkText(completion_string, i); - std::string new_detail = clang::ToString(text) + detail + " "; - detail = new_detail; - break; - } + case CXCompletionChunk_ResultType: { + CXString text = clang_getCompletionChunkText(completion_string, i); + std::string new_detail = clang::ToString(text) + detail + " "; + detail = new_detail; + break; + } - case CXCompletionChunk_LeftParen: - detail += "("; - insert += "("; - break; - case CXCompletionChunk_RightParen: - detail += ")"; - insert += ")"; - break; - case CXCompletionChunk_LeftBracket: - detail += "["; - insert += "["; - break; - case CXCompletionChunk_RightBracket: - detail += "]"; - insert += "]"; - break; - case CXCompletionChunk_LeftBrace: - detail += "{"; - insert += "{"; - break; - case CXCompletionChunk_RightBrace: - detail += "}"; - insert += "}"; - break; - case CXCompletionChunk_LeftAngle: - detail += "<"; - insert += "<"; - break; - case CXCompletionChunk_RightAngle: - detail += ">"; - insert += ">"; - break; - case CXCompletionChunk_Comma: - detail += ", "; - insert += ", "; - break; - case CXCompletionChunk_Colon: - detail += ":"; - insert += ":"; - break; - case CXCompletionChunk_SemiColon: - detail += ";"; - insert += ";"; - break; - case CXCompletionChunk_Equal: - detail += "="; - insert += "="; - break; - case CXCompletionChunk_HorizontalSpace: - case CXCompletionChunk_VerticalSpace: - detail += " "; - insert += " "; - break; + case CXCompletionChunk_LeftParen: + detail += "("; + insert += "("; + break; + case CXCompletionChunk_RightParen: + detail += ")"; + insert += ")"; + break; + case CXCompletionChunk_LeftBracket: + detail += "["; + insert += "["; + break; + case CXCompletionChunk_RightBracket: + detail += "]"; + insert += "]"; + break; + case CXCompletionChunk_LeftBrace: + detail += "{"; + insert += "{"; + break; + case CXCompletionChunk_RightBrace: + detail += "}"; + insert += "}"; + break; + case CXCompletionChunk_LeftAngle: + detail += "<"; + insert += "<"; + break; + case CXCompletionChunk_RightAngle: + detail += ">"; + insert += ">"; + break; + case CXCompletionChunk_Comma: + detail += ", "; + insert += ", "; + break; + case CXCompletionChunk_Colon: + detail += ":"; + insert += ":"; + break; + case CXCompletionChunk_SemiColon: + detail += ";"; + insert += ";"; + break; + case CXCompletionChunk_Equal: + detail += "="; + insert += "="; + break; + case CXCompletionChunk_HorizontalSpace: + case CXCompletionChunk_VerticalSpace: + detail += " "; + insert += " "; + break; } } } @@ -285,9 +297,12 @@ void EnsureDocumentParsed(ClangCompleteManager* manager, std::vector unsaved = session->working_files->AsUnsavedFiles(); - std::cerr << "[complete] Creating completion session with arguments " << StringJoin(args) << std::endl; - *tu = MakeUnique(index, session->file.filename, args, unsaved, Flags()); - std::cerr << "[complete] Done creating active; did_fail=" << (*tu)->did_fail << std::endl; + std::cerr << "[complete] Creating completion session with arguments " + << StringJoin(args) << std::endl; + *tu = MakeUnique(index, session->file.filename, args, + unsaved, Flags()); + std::cerr << "[complete] Done creating active; did_fail=" << (*tu)->did_fail + << std::endl; // Build diagnostics. if (manager->config_->diagnosticsOnParse && !(*tu)->did_fail) { @@ -306,11 +321,14 @@ void EnsureDocumentParsed(ClangCompleteManager* manager, void CompletionParseMain(ClangCompleteManager* completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. - ClangCompleteManager::ParseRequest request = completion_manager->parse_requests_.Dequeue(); + ClangCompleteManager::ParseRequest request = + completion_manager->parse_requests_.Dequeue(); // If we don't get a session then that means we don't care about the file // anymore - abandon the request. - std::shared_ptr session = completion_manager->TryGetSession(request.path, false /*create_if_needed*/); + std::shared_ptr session = + completion_manager->TryGetSession(request.path, + false /*create_if_needed*/); if (!session) continue; @@ -322,24 +340,29 @@ void CompletionParseMain(ClangCompleteManager* completion_manager) { } std::unique_ptr parsing; - EnsureDocumentParsed(completion_manager, session, &parsing, &session->index); + EnsureDocumentParsed(completion_manager, session, &parsing, + &session->index); // Activate new translation unit. - // tu_last_parsed_at is only read by this thread, so it doesn't need to be under the mutex. + // tu_last_parsed_at is only read by this thread, so it doesn't need to be + // under the mutex. session->tu_last_parsed_at = std::chrono::high_resolution_clock::now(); std::lock_guard lock(session->tu_lock); - std::cerr << "[completion] Swapping completion session for " << request.path << std::endl; + std::cerr << "[completion] Swapping completion session for " << request.path + << std::endl; session->tu = std::move(parsing); } } -void CompletionDiagnosticsDelayedRefreshMain(ClangCompleteManager* completion_manager) { +void CompletionDiagnosticsDelayedRefreshMain( + ClangCompleteManager* completion_manager) { constexpr int kSecondsToWaitForDiagnosticsRefresh = 5; // Refreshes diagnostics a few seconds after the final code completion, since // we don't get a language server request. while (true) { - std::unique_lock l(completion_manager->delayed_diagnostic_wakeup_mtx_); + std::unique_lock l( + completion_manager->delayed_diagnostic_wakeup_mtx_); completion_manager->delayed_diagnostic_wakeup_cv_.wait(l); // Check for spurious wakeup. @@ -350,15 +373,19 @@ void CompletionDiagnosticsDelayedRefreshMain(ClangCompleteManager* completion_ma // Get completion request info. if (!l.owns_lock()) l.lock(); - lsTextDocumentPositionParams location = *completion_manager->delayed_diagnostic_last_completion_position_; + lsTextDocumentPositionParams location = + *completion_manager->delayed_diagnostic_last_completion_position_; completion_manager->delayed_diagnostic_last_completion_position_.reset(); l.unlock(); // Wait five seconds. If there was another completion request, start the // waiting process over again. - std::this_thread::sleep_for(std::chrono::seconds(kSecondsToWaitForDiagnosticsRefresh)); + std::this_thread::sleep_for( + std::chrono::seconds(kSecondsToWaitForDiagnosticsRefresh)); l.lock(); - bool has_completion_since_sleeping = completion_manager->delayed_diagnostic_last_completion_position_.has_value(); + bool has_completion_since_sleeping = + completion_manager->delayed_diagnostic_last_completion_position_ + .has_value(); l.unlock(); if (has_completion_since_sleeping) continue; @@ -376,39 +403,42 @@ void CompletionDiagnosticsDelayedRefreshMain(ClangCompleteManager* completion_ma completion_manager->completion_request_.SetIfEmpty(std::move(request)); break; } - } } void CompletionQueryMain(ClangCompleteManager* completion_manager) { while (true) { // Fetching the completion request blocks until we have a request. - std::unique_ptr request = completion_manager->completion_request_.Take(); + std::unique_ptr request = + completion_manager->completion_request_.Take(); std::string path = request->location.textDocument.uri.GetPath(); - std::shared_ptr session = completion_manager->TryGetSession(path, true /*create_if_needed*/); + std::shared_ptr session = + completion_manager->TryGetSession(path, true /*create_if_needed*/); std::lock_guard lock(session->tu_lock); - EnsureDocumentParsed(completion_manager, session, &session->tu, &session->index); + EnsureDocumentParsed(completion_manager, session, &session->tu, + &session->index); // Language server is 0-based, clang is 1-based. unsigned line = request->location.position.line + 1; unsigned column = request->location.position.character + 1; - std::cerr << "[complete] Completing at " << line << ":" << column << std::endl; + std::cerr << "[complete] Completing at " << line << ":" << column + << std::endl; Timer timer; - std::vector unsaved = completion_manager->working_files_->AsUnsavedFiles(); + std::vector unsaved = + completion_manager->working_files_->AsUnsavedFiles(); timer.ResetAndPrint("[complete] Fetching unsaved files"); timer.Reset(); - unsigned const kCompleteOptions = CXCodeComplete_IncludeMacros | CXCodeComplete_IncludeBriefComments; + unsigned const kCompleteOptions = + CXCodeComplete_IncludeMacros | CXCodeComplete_IncludeBriefComments; CXCodeCompleteResults* cx_results = clang_codeCompleteAt( - session->tu->cx_tu, - session->file.filename.c_str(), line, column, - unsaved.data(), (unsigned)unsaved.size(), - kCompleteOptions); + session->tu->cx_tu, session->file.filename.c_str(), line, column, + unsaved.data(), (unsigned)unsaved.size(), kCompleteOptions); if (!cx_results) { timer.ResetAndPrint("[complete] Code completion failed"); if (request->on_complete) @@ -417,7 +447,8 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { } timer.ResetAndPrint("[complete] clangCodeCompleteAt"); - std::cerr << "[complete] Got " << cx_results->NumResults << " results" << std::endl; + std::cerr << "[complete] Got " << cx_results->NumResults << " results" + << std::endl; { if (request->on_complete) { @@ -428,14 +459,15 @@ 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, + // 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) + if (clang_getCompletionAvailability(result.CompletionString) == + CXAvailability_NotAvailable) continue; // TODO: fill in more data @@ -443,29 +475,40 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { // kind/label/detail/docs/sortText 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.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.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_result.push_back(ls_completion_item); } - timer.ResetAndPrint("[complete] Building " + std::to_string(ls_result.size()) + " completion results"); + timer.ResetAndPrint("[complete] Building " + + std::to_string(ls_result.size()) + + " completion results"); request->on_complete(ls_result, false /*is_cached_result*/); timer.ResetAndPrint("[complete] Running user-given completion func"); } if (completion_manager->config_->diagnosticsOnCodeCompletion) { - unsigned num_diagnostics = clang_codeCompleteGetNumDiagnostics(cx_results); + unsigned num_diagnostics = + clang_codeCompleteGetNumDiagnostics(cx_results); NonElidedVector ls_diagnostics; for (unsigned i = 0; i < num_diagnostics; ++i) { CXDiagnostic cx_diag = clang_codeCompleteGetDiagnostic(cx_results, i); - optional diagnostic = BuildAndDisposeDiagnostic(cx_diag, path); + optional diagnostic = + BuildAndDisposeDiagnostic(cx_diag, path); if (diagnostic) ls_diagnostics.push_back(*diagnostic); } - completion_manager->on_diagnostic_(session->file.filename, ls_diagnostics); + completion_manager->on_diagnostic_(session->file.filename, + ls_diagnostics); timer.ResetAndPrint("[complete] Build diagnostics"); } } @@ -477,8 +520,10 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { if (completion_manager->config_->diagnosticsOnCodeCompletion && request->is_user_completion) { { - std::lock_guard lock(completion_manager->delayed_diagnostic_wakeup_mtx_); - completion_manager->delayed_diagnostic_last_completion_position_ = request->location; + std::lock_guard lock( + completion_manager->delayed_diagnostic_wakeup_mtx_); + completion_manager->delayed_diagnostic_last_completion_position_ = + request->location; } completion_manager->delayed_diagnostic_wakeup_cv_.notify_one(); } @@ -489,19 +534,25 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) { } // namespace -CompletionSession::CompletionSession(const Project::Entry& file, WorkingFiles* working_files) - : file(file), working_files(working_files), index(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/) { - std::cerr << "[complete] CompletionSession::CompletionSession() for " << file.filename << std::endl; +CompletionSession::CompletionSession(const Project::Entry& file, + WorkingFiles* working_files) + : file(file), + working_files(working_files), + index(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/) { + std::cerr << "[complete] CompletionSession::CompletionSession() for " + << file.filename << std::endl; } 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) {} -std::shared_ptr LruSessionCache::TryGetEntry(const std::string& filename) { +std::shared_ptr LruSessionCache::TryGetEntry( + const std::string& filename) { for (int i = 0; i < entries_.size(); ++i) { if (entries_[i]->file.filename == filename) return entries_[i]; @@ -509,7 +560,8 @@ std::shared_ptr LruSessionCache::TryGetEntry(const std::strin return nullptr; } -std::shared_ptr LruSessionCache::TryTakeEntry(const std::string& filename) { +std::shared_ptr LruSessionCache::TryTakeEntry( + const std::string& filename) { for (int i = 0; i < entries_.size(); ++i) { if (entries_[i]->file.filename == filename) { std::shared_ptr result = entries_[i]; @@ -527,11 +579,18 @@ void LruSessionCache::InsertEntry(std::shared_ptr session) { } ClangCompleteManager::ParseRequest::ParseRequest(const std::string& path) - : request_time(std::chrono::high_resolution_clock::now()), path(path) {} + : request_time(std::chrono::high_resolution_clock::now()), path(path) {} -ClangCompleteManager::ClangCompleteManager(Config* config, Project* project, WorkingFiles* working_files, OnDiagnostic on_diagnostic) - : config_(config), project_(project), working_files_(working_files), on_diagnostic_(on_diagnostic), - view_sessions_(kMaxViewSessions), edit_sessions_(kMaxEditSessions) { +ClangCompleteManager::ClangCompleteManager(Config* config, + Project* project, + WorkingFiles* working_files, + OnDiagnostic on_diagnostic) + : config_(config), + project_(project), + working_files_(working_files), + on_diagnostic_(on_diagnostic), + view_sessions_(kMaxViewSessions), + edit_sessions_(kMaxEditSessions) { new std::thread([&]() { SetCurrentThreadName("completequery"); CompletionQueryMain(this); @@ -550,7 +609,9 @@ 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. auto request = MakeUnique(); @@ -572,9 +633,10 @@ void ClangCompleteManager::NotifyView(const std::string& filename) { if (view_sessions_.TryGetEntry(filename)) 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(std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_)); + project_->FindCompilationEntryForFile(filename), working_files_)); parse_requests_.Enqueue(ParseRequest(filename)); } @@ -590,14 +652,15 @@ void ClangCompleteManager::NotifyEdit(const std::string& filename) { if (edit_sessions_.TryGetEntry(filename)) return; - std::shared_ptr session = view_sessions_.TryTakeEntry(filename); + std::shared_ptr session = + view_sessions_.TryTakeEntry(filename); if (session) { edit_sessions_.InsertEntry(session); - } - else { - std::cerr << "[complete] Creating new edit code completion session for " << filename << std::endl; + } else { + std::cerr << "[complete] Creating new edit code completion session for " + << filename << std::endl; edit_sessions_.InsertEntry(std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_)); + project_->FindCompilationEntryForFile(filename), working_files_)); parse_requests_.PriorityEnqueue(ParseRequest(filename)); } } @@ -610,18 +673,22 @@ void ClangCompleteManager::NotifySave(const std::string& filename) { std::lock_guard lock(sessions_lock_); 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(std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_)); + project_->FindCompilationEntryForFile(filename), working_files_)); } parse_requests_.PriorityEnqueue(ParseRequest(filename)); } -std::shared_ptr ClangCompleteManager::TryGetSession(const std::string& filename, bool create_if_needed) { +std::shared_ptr ClangCompleteManager::TryGetSession( + const std::string& filename, + bool create_if_needed) { std::lock_guard lock(sessions_lock_); - std::shared_ptr session = edit_sessions_.TryGetEntry(filename); + std::shared_ptr session = + edit_sessions_.TryGetEntry(filename); if (!session) session = view_sessions_.TryGetEntry(filename); @@ -630,7 +697,7 @@ std::shared_ptr ClangCompleteManager::TryGetSession(const std // Create new session. Default to edited_sessions_ since invoking code // completion almost certainly implies an edit. edit_sessions_.InsertEntry(std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_)); + project_->FindCompilationEntryForFile(filename), working_files_)); session = edit_sessions_.TryGetEntry(filename); } diff --git a/src/clang_complete.h b/src/clang_complete.h index c06f173e..64a3ba31 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.h @@ -13,13 +13,15 @@ #include #include -struct CompletionSession : public std::enable_shared_from_this { +struct CompletionSession + : public std::enable_shared_from_this { Project::Entry file; WorkingFiles* working_files; clang::Index index; // When |tu| was last parsed. - optional> tu_last_parsed_at; + optional> + tu_last_parsed_at; // Acquired when |tu| is being used. std::mutex tu_lock; @@ -47,8 +49,12 @@ struct LruSessionCache { }; struct ClangCompleteManager { - using OnDiagnostic = std::function diagnostics)>; - using OnComplete = std::function& results, bool is_cached_result)>; + using OnDiagnostic = + std::function diagnostics)>; + using OnComplete = + std::function& results, + bool is_cached_result)>; struct ParseRequest { ParseRequest(const std::string& path); @@ -62,7 +68,10 @@ struct ClangCompleteManager { bool is_user_completion = false; }; - 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 @@ -79,7 +88,8 @@ struct ClangCompleteManager { // triggers a reparse. void NotifySave(const std::string& filename); - std::shared_ptr TryGetSession(const std::string& filename, bool create_if_needed); + std::shared_ptr TryGetSession(const std::string& filename, + bool create_if_needed); // TODO: make these configurable. const int kMaxViewSessions = 1; @@ -108,5 +118,6 @@ struct ClangCompleteManager { std::mutex delayed_diagnostic_wakeup_mtx_; std::condition_variable delayed_diagnostic_wakeup_cv_; // Access under |delayed_diagnostic_wakeup_mtx_|. - optional delayed_diagnostic_last_completion_position_; + optional + delayed_diagnostic_last_completion_position_; }; diff --git a/src/clang_utils.cc b/src/clang_utils.cc index cd3de430..c0b11f0c 100644 --- a/src/clang_utils.cc +++ b/src/clang_utils.cc @@ -10,24 +10,24 @@ lsRange GetLsRangeForFixIt(const CXSourceRange& range) { CXSourceLocation end = clang_getRangeEnd(range); unsigned int start_line, start_column; - clang_getSpellingLocation(start, nullptr, &start_line, &start_column, nullptr); + clang_getSpellingLocation(start, nullptr, &start_line, &start_column, + nullptr); unsigned int end_line, end_column; clang_getSpellingLocation(end, nullptr, &end_line, &end_column, nullptr); - return lsRange( - lsPosition(start_line - 1, start_column - 1) /*start*/, - lsPosition(end_line - 1, end_column) /*end*/); + return lsRange(lsPosition(start_line - 1, start_column - 1) /*start*/, + lsPosition(end_line - 1, end_column) /*end*/); } } // namespace -optional BuildAndDisposeDiagnostic( - CXDiagnostic diagnostic, const std::string& path) { +optional BuildAndDisposeDiagnostic(CXDiagnostic diagnostic, + const std::string& path) { // Get diagnostic location. CXFile file; unsigned int line, column; - clang_getSpellingLocation( - clang_getDiagnosticLocation(diagnostic), &file, &line, &column, nullptr); + clang_getSpellingLocation(clang_getDiagnosticLocation(diagnostic), &file, + &line, &column, nullptr); // Only report diagnostics in the same file. Using // clang_Location_isInSystemHeader causes crashes for some reason. @@ -43,12 +43,15 @@ optional BuildAndDisposeDiagnostic( // TODO: ls_diagnostic.range is lsRange, we have Range. We should only be // storing Range types when inside the indexer so that index <-> buffer // remapping logic is applied. - ls_diagnostic.range = lsRange(lsPosition(line - 1, column), lsPosition(line - 1, column)); + ls_diagnostic.range = + lsRange(lsPosition(line - 1, column), lsPosition(line - 1, column)); - ls_diagnostic.message = clang::ToString(clang_getDiagnosticSpelling(diagnostic)); + ls_diagnostic.message = + clang::ToString(clang_getDiagnosticSpelling(diagnostic)); // Append the flag that enables this diagnostic, ie, [-Wswitch] - std::string enabling_flag = clang::ToString(clang_getDiagnosticOption(diagnostic, nullptr)); + std::string enabling_flag = + clang::ToString(clang_getDiagnosticOption(diagnostic, nullptr)); if (!enabling_flag.empty()) ls_diagnostic.message += " [" + enabling_flag + "]"; diff --git a/src/clang_utils.h b/src/clang_utils.h index dcc2d87a..0bd8057e 100644 --- a/src/clang_utils.h +++ b/src/clang_utils.h @@ -4,13 +4,14 @@ #include -#include #include +#include + using namespace std::experimental; -optional BuildAndDisposeDiagnostic( - CXDiagnostic diagnostic, const std::string& path); +optional BuildAndDisposeDiagnostic(CXDiagnostic diagnostic, + const std::string& path); // Returns the absolute path to |file|. std::string FileName(CXFile file); diff --git a/src/command_line.cc b/src/command_line.cc index 38d99cf5..a6655c45 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -3,26 +3,27 @@ #include "cache.h" #include "clang_complete.h" #include "file_consumer.h" -#include "match.h" #include "include_complete.h" -#include "ipc_manager.h" #include "indexer.h" -#include "message_queue.h" -#include "query.h" -#include "query_utils.h" +#include "ipc_manager.h" #include "language_server_api.h" #include "lex_utils.h" +#include "match.h" +#include "message_queue.h" #include "options.h" -#include "project.h" #include "platform.h" +#include "project.h" +#include "query.h" +#include "query_utils.h" #include "serializer.h" #include "standard_includes.h" #include "test.h" -#include "timer.h" #include "threaded_queue.h" +#include "timer.h" #include "work_thread.h" #include "working_files.h" + #include #include "tiny-process-library/process.hpp" @@ -32,22 +33,23 @@ #include #include -#include #include +#include #include #include -#include #include -#include +#include #include +#include #include + // TODO: provide a feature like 'https://github.com/goldsborough/clang-expand', // ie, a fully linear view of a function with inline function calls expanded. // We can probably use vscode decorators to achieve it. -// TODO: implement ThreadPool type which monitors CPU usage / number of work items -// per second completed and scales up/down number of running threads. +// TODO: implement ThreadPool type which monitors CPU usage / number of work +// items per second completed and scales up/down number of running threads. namespace { @@ -107,75 +109,29 @@ struct CodeCompleteCache { } }; - - - - - - - - - - - - - - - - - - - - - -// This function returns true if e2e timing should be displayed for the given IpcId. +// This function returns true if e2e timing should be displayed for the given +// IpcId. bool ShouldDisplayIpcTiming(IpcId id) { switch (id) { - case IpcId::TextDocumentPublishDiagnostics: - case IpcId::CqueryPublishInactiveRegions: - return false; - default: - return true; + case IpcId::TextDocumentPublishDiagnostics: + case IpcId::CqueryPublishInactiveRegions: + return false; + default: + return true; } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PushBack(NonElidedVector* result, optional location) { +void PushBack(NonElidedVector* result, + optional location) { if (location) result->push_back(*location); } -bool FindFileOrFail(QueryDatabase* db, lsRequestId id, const std::string& absolute_path, QueryFile** out_query_file, QueryFileId* out_file_id = nullptr) { +bool FindFileOrFail(QueryDatabase* db, + lsRequestId id, + const std::string& absolute_path, + QueryFile** out_query_file, + QueryFileId* out_file_id = nullptr) { auto it = db->usr_to_file.find(LowerPathIfCaseInsensitive(absolute_path)); if (it != db->usr_to_file.end()) { optional& file = db->files[it->second.id]; @@ -201,8 +157,8 @@ bool FindFileOrFail(QueryDatabase* db, lsRequestId id, const std::string& absolu return false; } - -void PublishInactiveLines(WorkingFile* working_file, const std::vector& inactive) { +void PublishInactiveLines(WorkingFile* working_file, + const std::vector& inactive) { Out_CquerySetInactiveRegion out; out.params.uri = lsDocumentUri::FromPath(working_file->filename); for (Range skipped : inactive) { @@ -210,12 +166,12 @@ void PublishInactiveLines(WorkingFile* working_file, const std::vector& i if (ls_skipped) out.params.inactiveRegions.push_back(*ls_skipped); } - IpcManager::instance()->SendOutMessageToClient(IpcId::CqueryPublishInactiveRegions, out); + IpcManager::instance()->SendOutMessageToClient( + IpcId::CqueryPublishInactiveRegions, out); } - - -optional FindIncludeLine(const std::vector& lines, const std::string& full_include_line) { +optional FindIncludeLine(const std::vector& lines, + const std::string& full_include_line) { // // This returns an include line. For example, // @@ -265,21 +221,29 @@ optional FindIncludeLine(const std::vector& lines, const std:: return 0; } -optional GetImplementationFile(QueryDatabase* db, QueryFileId file_id, QueryFile* file) { +optional GetImplementationFile(QueryDatabase* db, + QueryFileId file_id, + QueryFile* file) { for (SymbolRef sym : file->def.outline) { switch (sym.idx.kind) { case SymbolKind::Func: { optional& func = db->funcs[sym.idx.idx]; - // Note: we ignore the definition if it is in the same file (ie, possibly a header). - if (func && func->def.definition_extent && func->def.definition_extent->path != file_id) + // Note: we ignore the definition if it is in the same file (ie, + // possibly a header). + if (func && func->def.definition_extent && + func->def.definition_extent->path != file_id) { return func->def.definition_extent->path; + } break; } case SymbolKind::Var: { optional& var = db->vars[sym.idx.idx]; - // Note: we ignore the definition if it is in the same file (ie, possibly a header). - if (var && var->def.definition_extent && var->def.definition_extent->path != file_id) + // Note: we ignore the definition if it is in the same file (ie, + // possibly a header). + if (var && var->def.definition_extent && + var->def.definition_extent->path != file_id) { return db->vars[sym.idx.idx]->def.definition_extent->path; + } break; } default: @@ -314,7 +278,10 @@ optional GetImplementationFile(QueryDatabase* db, QueryFileId file_ return nullopt; } -void EnsureImplFile(QueryDatabase* db, QueryFileId file_id, optional& impl_uri, optional& impl_file_id) { +void EnsureImplFile(QueryDatabase* db, + QueryFileId file_id, + optional& impl_uri, + optional& impl_file_id) { if (!impl_uri.has_value()) { optional& file = db->files[file_id.id]; assert(file); @@ -331,7 +298,13 @@ void EnsureImplFile(QueryDatabase* db, QueryFileId file_id, optional BuildAutoImplementForFunction(QueryDatabase* db, WorkingFiles* working_files, WorkingFile* working_file, int default_line, QueryFileId decl_file_id, QueryFileId impl_file_id, QueryFunc& func) { +optional BuildAutoImplementForFunction(QueryDatabase* db, + WorkingFiles* working_files, + WorkingFile* working_file, + int default_line, + QueryFileId decl_file_id, + QueryFileId impl_file_id, + QueryFunc& func) { for (const QueryLocation& decl : func.declarations) { if (decl.path != decl_file_id) continue; @@ -343,20 +316,23 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, WorkingFil optional type_name; optional same_file_insert_end; if (func.def.declaring_type) { - optional& declaring_type = db->types[func.def.declaring_type->id]; + optional& declaring_type = + db->types[func.def.declaring_type->id]; if (declaring_type) { type_name = declaring_type->def.short_name; - optional ls_type_def_extent = GetLsRange(working_file, declaring_type->def.definition_extent->range); + optional ls_type_def_extent = GetLsRange( + working_file, declaring_type->def.definition_extent->range); if (ls_type_def_extent) { same_file_insert_end = ls_type_def_extent->end; - same_file_insert_end->character += 1; // move past semicolon. + same_file_insert_end->character += 1; // move past semicolon. } } } std::string insert_text; int newlines_after_name = 0; - LexFunctionDeclaration(working_file->buffer_content, ls_decl->start, type_name, &insert_text, &newlines_after_name); + LexFunctionDeclaration(working_file->buffer_content, ls_decl->start, + type_name, &insert_text, &newlines_after_name); if (!same_file_insert_end) { same_file_insert_end = ls_decl->end; @@ -370,8 +346,7 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, WorkingFil edit.range.start = *same_file_insert_end; edit.range.end = *same_file_insert_end; edit.newText = "\n\n" + insert_text; - } - else { + } else { lsPosition best_pos; best_pos.line = default_line; int best_dist = INT_MAX; @@ -389,7 +364,8 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, WorkingFil if (func_decl.path == decl_file_id) { int dist = func_decl.range.start.line - decl.range.start.line; if (abs(dist) < abs(best_dist)) { - optional def_loc = GetLsLocation(db, working_files, *sym_func->def.definition_extent); + optional def_loc = GetLsLocation( + db, working_files, *sym_func->def.definition_extent); if (!def_loc) continue; @@ -407,11 +383,6 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, WorkingFil } case SymbolKind::Var: { // TODO: handle vars. - - //optional& var = db->vars[sym.idx.idx]; - //if (!var || !var->def.definition_extent) - // continue; - break; } case SymbolKind::Invalid: @@ -423,7 +394,6 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, WorkingFil } } - edit.range.start = best_pos; edit.range.end = best_pos; if (best_dist < 0) @@ -438,12 +408,15 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, WorkingFil return nullopt; } -void EmitDiagnostics(WorkingFiles* working_files, std::string path, NonElidedVector diagnostics) { +void EmitDiagnostics(WorkingFiles* working_files, + std::string path, + NonElidedVector diagnostics) { // Emit diagnostics. Out_TextDocumentPublishDiagnostics diagnostic_response; diagnostic_response.params.uri = lsDocumentUri::FromPath(path); diagnostic_response.params.diagnostics = diagnostics; - IpcManager::instance()->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diagnostic_response); + IpcManager::instance()->SendOutMessageToClient( + IpcId::TextDocumentPublishDiagnostics, diagnostic_response); // Cache diagnostics so we can show fixits. working_files->DoActionOnFile(path, [&](WorkingFile* working_file) { @@ -457,7 +430,7 @@ void EmitDiagnostics(WorkingFiles* working_files, std::string path, NonElidedVec // when given 1000+ completion items. void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, const std::string& complete_text) { - // Used to inject more completions. +// Used to inject more completions. #if false const size_t kNumIterations = 250; size_t size = complete_response->result.items.size(); @@ -471,17 +444,13 @@ void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, } #endif - const size_t kMaxResultSize = 100u; if (complete_response->result.items.size() > kMaxResultSize) { - //std::cerr << "!!! Filtering " << complete_response->result.items.size() << " results using " << complete_text << std::endl; - complete_response->result.isIncomplete = true; if (complete_text.empty()) { complete_response->result.items.resize(kMaxResultSize); - } - else { + } else { NonElidedVector filtered_result; filtered_result.reserve(kMaxResultSize); @@ -516,36 +485,24 @@ void FilterCompletionResponse(Out_TextDocumentComplete* complete_response, complete_response->result.items = filtered_result; } - - //std::cerr << "!! Filtering resulted in " << complete_response->result.items.size() << " entries" << std::endl; } } - - - - - - - - - - - - - - - - - struct Index_Request { std::string path; - std::vector args; // TODO: make this a string that is parsed lazily. + // TODO: make |args| a string that is parsed lazily. + std::vector args; bool is_interactive; - optional contents; // Preloaded contents. Useful for tests. + optional contents; // Preloaded contents. Useful for tests. - Index_Request(const std::string& path, const std::vector& args, bool is_interactive, optional contents) - : path(path), args(args), is_interactive(is_interactive), contents(contents) {} + Index_Request(const std::string& path, + const std::vector& args, + bool is_interactive, + optional contents) + : path(path), + args(args), + is_interactive(is_interactive), + contents(contents) {} }; struct Index_DoIdMap { @@ -557,15 +514,14 @@ struct Index_DoIdMap { bool write_to_disk = false; bool load_previous = false; - Index_DoIdMap( - std::unique_ptr current, - PerformanceImportFile perf, - bool is_interactive, - bool write_to_disk) - : current(std::move(current)), - perf(perf), - is_interactive(is_interactive), - write_to_disk(write_to_disk) {} + Index_DoIdMap(std::unique_ptr current, + PerformanceImportFile perf, + bool is_interactive, + bool write_to_disk) + : current(std::move(current)), + perf(perf), + is_interactive(is_interactive), + write_to_disk(write_to_disk) {} }; struct Index_OnIdMapped { @@ -574,7 +530,7 @@ struct Index_OnIdMapped { std::unique_ptr ids; File(std::unique_ptr file, std::unique_ptr ids) - : file(std::move(file)), ids(std::move(ids)) {} + : file(std::move(file)), ids(std::move(ids)) {} }; std::unique_ptr previous; @@ -584,23 +540,20 @@ struct Index_OnIdMapped { bool is_interactive; bool write_to_disk; - Index_OnIdMapped( - PerformanceImportFile perf, - bool is_interactive, - bool write_to_disk) - : perf(perf), - is_interactive(is_interactive), - write_to_disk(write_to_disk) {} + Index_OnIdMapped(PerformanceImportFile perf, + bool is_interactive, + bool write_to_disk) + : perf(perf), + is_interactive(is_interactive), + write_to_disk(write_to_disk) {} }; struct Index_OnIndexed { IndexUpdate update; PerformanceImportFile perf; - Index_OnIndexed( - IndexUpdate& update, - PerformanceImportFile perf) - : update(update), perf(perf) {} + Index_OnIndexed(IndexUpdate& update, PerformanceImportFile perf) + : update(update), perf(perf) {} }; @@ -653,15 +606,17 @@ struct QueueManager { Index_OnIdMappedQueue on_id_mapped; Index_OnIndexedQueue on_indexed; - QueueManager(MultiQueueWaiter* waiter) : index_request(waiter), do_id_map(waiter), load_previous_index(waiter), on_id_mapped(waiter), on_indexed(waiter) {} + QueueManager(MultiQueueWaiter* waiter) + : index_request(waiter), + do_id_map(waiter), + load_previous_index(waiter), + on_id_mapped(waiter), + on_indexed(waiter) {} bool HasWork() { - return - !index_request.IsEmpty() || - !do_id_map.IsEmpty() || - !load_previous_index.IsEmpty() || - !on_id_mapped.IsEmpty() || - !on_indexed.IsEmpty(); + return !index_request.IsEmpty() || !do_id_map.IsEmpty() || + !load_previous_index.IsEmpty() || !on_id_mapped.IsEmpty() || + !on_indexed.IsEmpty(); } }; @@ -700,12 +655,10 @@ void RegisterMessageTypes() { MessageRegistry::instance()->Register(); } - - - - - -void InsertSymbolIntoResult(QueryDatabase* db, WorkingFiles* working_files, SymbolIdx symbol, std::vector* result) { +void InsertSymbolIntoResult(QueryDatabase* db, + WorkingFiles* working_files, + SymbolIdx symbol, + std::vector* result) { optional info = GetSymbolInfo(db, working_files, symbol); if (!info) return; @@ -718,7 +671,8 @@ void InsertSymbolIntoResult(QueryDatabase* db, WorkingFiles* working_files, Symb location = decls[0]; } - optional ls_location = GetLsLocation(db, working_files, *location); + optional ls_location = + GetLsLocation(db, working_files, *location); if (!ls_location) return; info->location = *ls_location; @@ -750,9 +704,7 @@ struct ImportManager { } // Returns true if there any any files currently being imported. - bool HasActiveQuerydbImports() { - return !querydb_processing_.empty(); - } + bool HasActiveQuerydbImports() { return !querydb_processing_.empty(); } std::unordered_set querydb_processing_; @@ -797,7 +749,8 @@ struct CacheLoader { // important for import perf, as during dependency checking the same files are // checked over and over again if they are common headers. struct TimestampManager { - optional GetLastCachedModificationTime(CacheLoader* cache_loader, const std::string& path) { + optional GetLastCachedModificationTime(CacheLoader* cache_loader, + const std::string& path) { { std::lock_guard guard(mutex_); auto it = timestamps_.find(path); @@ -812,16 +765,17 @@ struct TimestampManager { return file->last_modification_time; } - void UpdateCachedModificationTime(const std::string& path, int64_t timestamp) { + void UpdateCachedModificationTime(const std::string& path, + int64_t timestamp) { std::lock_guard guard(mutex_); timestamps_[path] = timestamp; } - std::mutex mutex_; // TODO: use std::shared_mutex so we can have multiple readers. + // TODO: use std::shared_mutex so we can have multiple readers. + std::mutex mutex_; std::unordered_map timestamps_; }; - struct IndexManager { std::unordered_set files_being_indexed_; std::mutex mutex_; @@ -845,9 +799,9 @@ struct IndexManager { } }; - } // namespace +enum class FileParseQuery { NeedsParse, DoesNotNeedParse, BadFile }; @@ -885,11 +839,6 @@ struct IndexManager { -enum class FileParseQuery { - NeedsParse, - DoesNotNeedParse, - BadFile -}; std::vector DoParseFile( Config* config, @@ -924,11 +873,14 @@ std::vector DoParseFile( if (!modification_timestamp) return FileParseQuery::BadFile; - optional last_cached_modification = timestamp_manager->GetLastCachedModificationTime(cache_loader, path); + optional last_cached_modification = + timestamp_manager->GetLastCachedModificationTime(cache_loader, path); - if (!last_cached_modification || modification_timestamp != *last_cached_modification) { + if (!last_cached_modification || + modification_timestamp != *last_cached_modification) { file_consumer_shared->Reset(path); - timestamp_manager->UpdateCachedModificationTime(path, *modification_timestamp); + timestamp_manager->UpdateCachedModificationTime( + path, *modification_timestamp); return FileParseQuery::NeedsParse; } return FileParseQuery::DoesNotNeedParse; @@ -943,8 +895,10 @@ std::vector DoParseFile( for (const std::string& dependency : previous_index->dependencies) { assert(!dependency.empty()); - if (file_needs_parse(dependency, true /*is_dependency*/) == FileParseQuery::NeedsParse) { - LOG_S(INFO) << "Timestamp has changed for " << dependency << " (via " << previous_index->path << ")"; + if (file_needs_parse(dependency, true /*is_dependency*/) == + FileParseQuery::NeedsParse) { + LOG_S(INFO) << "Timestamp has changed for " << dependency << " (via " + << previous_index->path << ")"; needs_reparse = true; // SUBTLE: Do not break here, as |file_consumer_shared| is updated // inside of |file_needs_parse|. @@ -957,15 +911,19 @@ std::vector DoParseFile( // TODO/FIXME: real perf PerformanceImportFile perf; - result.push_back(Index_DoIdMap(cache_loader->TryTakeOrLoad(path), perf, is_interactive, false /*write_to_disk*/)); + result.push_back(Index_DoIdMap(cache_loader->TryTakeOrLoad(path), perf, + is_interactive, false /*write_to_disk*/)); for (const std::string& dependency : previous_index->dependencies) { // Only actually load the file if we haven't loaded it yet. Important // for perf when files have lots of common dependencies. if (!file_consumer_shared->Mark(dependency)) continue; - LOG_S(INFO) << "Emitting index result for " << dependency << " (via " << previous_index->path << ")"; - result.push_back(Index_DoIdMap(cache_loader->TryTakeOrLoad(dependency), perf, is_interactive, false /*write_to_disk*/)); + LOG_S(INFO) << "Emitting index result for " << dependency << " (via " + << previous_index->path << ")"; + result.push_back(Index_DoIdMap(cache_loader->TryTakeOrLoad(dependency), + perf, is_interactive, + false /*write_to_disk*/)); } return result; } @@ -1013,10 +971,9 @@ std::vector DoParseFile( PerformanceImportFile perf; std::vector> indexes = Parse( - config, file_consumer_shared, - path, args, file_contents, - &perf, index); - // LOG_S(INFO) << "Parsing " << path << " gave " << indexes.size() << " indexes"; + config, file_consumer_shared, path, args, file_contents, &perf, index); + // LOG_S(INFO) << "Parsing " << path << " gave " << indexes.size() << " + // indexes"; for (std::unique_ptr& new_index : indexes) { Timer time; @@ -1024,26 +981,26 @@ std::vector DoParseFile( if (is_interactive) EmitDiagnostics(working_files, new_index->path, new_index->diagnostics_); - // TODO: don't load cached index. We don't need to do this when indexer always exports dependency tree. - // Sanity check that verifies we did not generate a new index for a file whose timestamp did not change. + // TODO: don't load cached index. We don't need to do this when indexer + // always exports dependency tree. Sanity check that verifies we did not + // generate a new index for a file whose timestamp did not change. //{ // IndexFile* previous_index = cache_loader->TryLoad(new_index->path); - // assert(!previous_index || GetLastModificationTime(new_index->path) != previous_index->last_modification_time); + // assert(!previous_index || GetLastModificationTime(new_index->path) != + // previous_index->last_modification_time); //} // Note: we are reusing the parent perf. perf.index_load_cached = time.ElapsedMicrosecondsAndReset(); LOG_S(INFO) << "Emitting index result for " << new_index->path; - result.push_back(Index_DoIdMap(std::move(new_index), perf, is_interactive, true /*write_to_disk*/)); + result.push_back(Index_DoIdMap(std::move(new_index), perf, is_interactive, + true /*write_to_disk*/)); } return result; } - - - std::vector ParseFile( Config* config, WorkingFiles* working_files, @@ -1054,7 +1011,6 @@ std::vector ParseFile( bool is_interactive, const Project::Entry& entry, const optional& contents) { - optional file_contents; if (contents) file_contents = FileContents(entry.filename, *contents); @@ -1066,18 +1022,18 @@ std::vector ParseFile( // complain about if indexed by itself. IndexFile* entry_cache = cache_loader.TryLoad(entry.filename); std::string tu_path = entry_cache ? entry_cache->import_file : entry.filename; - return DoParseFile(config, working_files, index, file_consumer_shared, timestamp_manager, import_manager, &cache_loader, is_interactive, tu_path, entry.args, file_contents); + return DoParseFile(config, working_files, index, file_consumer_shared, + timestamp_manager, import_manager, &cache_loader, + is_interactive, tu_path, entry.args, file_contents); } -bool IndexMain_DoParse( - Config* config, - WorkingFiles* working_files, - QueueManager* queue, - FileConsumer::SharedState* file_consumer_shared, - TimestampManager* timestamp_manager, - ImportManager* import_manager, - clang::Index* index) { - +bool IndexMain_DoParse(Config* config, + WorkingFiles* working_files, + QueueManager* queue, + FileConsumer::SharedState* file_consumer_shared, + TimestampManager* timestamp_manager, + ImportManager* import_manager, + clang::Index* index) { optional request = queue->index_request.TryDequeue(); if (!request) return false; @@ -1085,7 +1041,9 @@ bool IndexMain_DoParse( Project::Entry entry; entry.filename = request->path; entry.args = request->args; - std::vector responses = ParseFile(config, working_files, index, file_consumer_shared, timestamp_manager, import_manager, request->is_interactive, entry, request->contents); + std::vector responses = ParseFile( + config, working_files, index, file_consumer_shared, timestamp_manager, + import_manager, request->is_interactive, entry, request->contents); // Don't bother sending an IdMap request if there are no responses. if (responses.empty()) @@ -1096,10 +1054,9 @@ bool IndexMain_DoParse( return true; } -bool IndexMain_DoCreateIndexUpdate( - Config* config, - QueueManager* queue, - TimestampManager* timestamp_manager) { +bool IndexMain_DoCreateIndexUpdate(Config* config, + QueueManager* queue, + TimestampManager* timestamp_manager) { optional response = queue->on_id_mapped.TryDequeue(); if (!response) return false; @@ -1109,30 +1066,34 @@ bool IndexMain_DoCreateIndexUpdate( IdMap* previous_id_map = nullptr; IndexFile* previous_index = nullptr; if (response->previous) { - LOG_S(INFO) << "Creating delta update for " << response->previous->file->path; + LOG_S(INFO) << "Creating delta update for " + << response->previous->file->path; previous_id_map = response->previous->ids.get(); previous_index = response->previous->file.get(); } // Build delta update. - IndexUpdate update = IndexUpdate::CreateDelta( - previous_id_map, response->current->ids.get(), - previous_index, response->current->file.get()); + IndexUpdate update = + IndexUpdate::CreateDelta(previous_id_map, response->current->ids.get(), + previous_index, response->current->file.get()); response->perf.index_make_delta = time.ElapsedMicrosecondsAndReset(); // Write current index to disk if requested. if (response->write_to_disk) { - LOG_S(INFO) << "Writing cached index to disk for " << response->current->file->path; + LOG_S(INFO) << "Writing cached index to disk for " + << response->current->file->path; time.Reset(); WriteToCache(config, *response->current->file); response->perf.index_save_to_disk = time.ElapsedMicrosecondsAndReset(); - timestamp_manager->UpdateCachedModificationTime(response->current->file->path, response->current->file->last_modification_time); + timestamp_manager->UpdateCachedModificationTime( + response->current->file->path, + response->current->file->last_modification_time); } #if false -#define PRINT_SECTION(name) \ - if (response->perf.name) {\ - total += response->perf.name; \ +#define PRINT_SECTION(name) \ + if (response->perf.name) { \ + total += response->perf.name; \ output << " " << #name << ": " << FormatMicroseconds(response->perf.name); \ } std::stringstream output; @@ -1166,7 +1127,9 @@ bool IndexMain_LoadPreviousIndex(Config* config, QueueManager* queue) { return false; response->previous = LoadCachedIndex(config, response->current->path); - LOG_IF_S(ERROR, !response->previous) << "Unable to load previous index for already imported index " << response->current->path; + LOG_IF_S(ERROR, !response->previous) + << "Unable to load previous index for already imported index " + << response->current->path; queue->do_id_map.Enqueue(std::move(*response)); return true; @@ -1196,15 +1159,14 @@ bool IndexMergeIndexUpdates(QueueManager* queue) { } } -WorkThread::Result IndexMain( - Config* config, - FileConsumer::SharedState* file_consumer_shared, - TimestampManager* timestamp_manager, - ImportManager* import_manager, - Project* project, - WorkingFiles* working_files, - MultiQueueWaiter* waiter, - QueueManager* queue) { +WorkThread::Result IndexMain(Config* config, + FileConsumer::SharedState* file_consumer_shared, + TimestampManager* timestamp_manager, + ImportManager* import_manager, + Project* project, + WorkingFiles* working_files, + MultiQueueWaiter* waiter, + QueueManager* queue) { // TODO: dispose of index after it is not used for a while. clang::Index index(1, 0); @@ -1218,7 +1180,9 @@ WorkThread::Result IndexMain( // IndexMain_DoCreateIndexUpdate so we don't starve querydb from doing any // work. Running both also lets the user query the partially constructed // index. - bool did_parse = IndexMain_DoParse(config, working_files, queue, file_consumer_shared, timestamp_manager, import_manager, &index); + bool did_parse = + IndexMain_DoParse(config, working_files, queue, file_consumer_shared, + timestamp_manager, import_manager, &index); bool did_create_update = IndexMain_DoCreateIndexUpdate(config, queue, timestamp_manager); @@ -1233,14 +1197,19 @@ WorkThread::Result IndexMain( // We didn't do any work, so wait for a notification. if (!did_parse && !did_create_update && !did_merge && !did_load_previous) { - waiter->Wait( - {&queue->index_request, &queue->on_id_mapped, &queue->load_previous_index, &queue->on_indexed}); + waiter->Wait({&queue->index_request, &queue->on_id_mapped, + &queue->load_previous_index, &queue->on_indexed}); } - return queue->HasWork() ? WorkThread::Result::MoreWork : WorkThread::Result::NoWork; + return queue->HasWork() ? WorkThread::Result::MoreWork + : WorkThread::Result::NoWork; } -bool QueryDb_ImportMain(Config* config, QueryDatabase* db, ImportManager* import_manager, QueueManager* queue, WorkingFiles* working_files) { +bool QueryDb_ImportMain(Config* config, + QueryDatabase* db, + ImportManager* import_manager, + QueueManager* queue, + WorkingFiles* working_files) { bool did_work = false; while (true) { @@ -1257,26 +1226,29 @@ bool QueryDb_ImportMain(Config* config, QueryDatabase* db, ImportManager* import // If the request does not have previous state and we have already imported // it, load the previous state from disk and rerun IdMap logic later. Do not // do this if we have already attempted in the past. - if (!request->load_previous && - !request->previous && - db->usr_to_file.find(LowerPathIfCaseInsensitive(request->current->path)) != db->usr_to_file.end()) { + if (!request->load_previous && !request->previous && + db->usr_to_file.find(LowerPathIfCaseInsensitive( + request->current->path)) != db->usr_to_file.end()) { assert(!request->load_previous); request->load_previous = true; queue->load_previous_index.Enqueue(std::move(*request)); continue; } - Index_OnIdMapped response(request->perf, request->is_interactive, request->write_to_disk); + Index_OnIdMapped response(request->perf, request->is_interactive, + request->write_to_disk); Timer time; assert(request->current); - auto make_map = [db](std::unique_ptr file) -> std::unique_ptr { + auto make_map = [db](std::unique_ptr file) + -> std::unique_ptr { if (!file) return nullptr; auto id_map = MakeUnique(db, file->id_cache); - return MakeUnique(std::move(file), std::move(id_map)); + return MakeUnique(std::move(file), + std::move(id_map)); }; response.current = make_map(std::move(request->current)); response.previous = make_map(std::move(request->previous)); @@ -1299,14 +1271,18 @@ bool QueryDb_ImportMain(Config* config, QueryDatabase* db, ImportManager* import // a real problem in practice we can load the file in a previous stage. // It should be fine though because we only do it if the user has the // file open. - WorkingFile* working_file = working_files->GetFileByFilename(updated_file.path); + WorkingFile* working_file = + working_files->GetFileByFilename(updated_file.path); if (working_file) { - optional cached_file_contents = LoadCachedFileContents(config, updated_file.path); + optional cached_file_contents = + LoadCachedFileContents(config, updated_file.path); if (cached_file_contents) working_file->SetIndexContent(*cached_file_contents); else working_file->SetIndexContent(working_file->buffer_content); - time.ResetAndPrint("Update WorkingFile index contents (via disk load) for " + updated_file.path); + time.ResetAndPrint( + "Update WorkingFile index contents (via disk load) for " + + updated_file.path); } // PERF: This will acquire a lock. If querydb ends being up being slow we @@ -1316,9 +1292,11 @@ bool QueryDb_ImportMain(Config* config, QueryDatabase* db, ImportManager* import time.Reset(); db->ApplyIndexUpdate(&response->update); - time.ResetAndPrint("Applying index update for " + StringJoinMap(response->update.files_def_update, [](const QueryFile::DefUpdate& value) { - return value.path; - })); + time.ResetAndPrint("Applying index update for " + + StringJoinMap(response->update.files_def_update, + [](const QueryFile::DefUpdate& value) { + return value.path; + })); } return did_work; @@ -1399,30 +1377,32 @@ bool QueryDb_ImportMain(Config* config, QueryDatabase* db, ImportManager* import -bool QueryDbMainLoop( - Config* config, - QueryDatabase* db, - bool* exit_when_idle, - MultiQueueWaiter* waiter, - QueueManager* queue, - Project* project, - FileConsumer::SharedState* file_consumer_shared, - ImportManager* import_manager, - TimestampManager* timestamp_manager, - WorkingFiles* working_files, - ClangCompleteManager* clang_complete, - IncludeComplete* include_complete, - CodeCompleteCache* global_code_complete_cache, - CodeCompleteCache* non_global_code_complete_cache, - CodeCompleteCache* signature_cache) { + + + +bool QueryDbMainLoop(Config* config, + QueryDatabase* db, + bool* exit_when_idle, + MultiQueueWaiter* waiter, + QueueManager* queue, + Project* project, + FileConsumer::SharedState* file_consumer_shared, + ImportManager* import_manager, + TimestampManager* timestamp_manager, + WorkingFiles* working_files, + ClangCompleteManager* clang_complete, + IncludeComplete* include_complete, + CodeCompleteCache* global_code_complete_cache, + CodeCompleteCache* non_global_code_complete_cache, + CodeCompleteCache* signature_cache) { IpcManager* ipc = IpcManager::instance(); bool did_work = false; - std::vector> messages = ipc->GetMessages(IpcManager::Destination::Server); + std::vector> messages = + ipc->GetMessages(IpcManager::Destination::Server); for (auto& message : messages) { did_work = true; - //std::cerr << "[querydb] Processing message " << IpcIdToString(message->method_id) << std::endl; switch (message->method_id) { case IpcId::Initialize: { @@ -1437,10 +1417,11 @@ bool QueryDbMainLoop( if (request->params.rootUri) { std::string project_path = request->params.rootUri->GetPath(); LOG_S(INFO) << "[querydb] Initialize in directory " << project_path - << " with uri " << request->params.rootUri->raw_uri; + << " with uri " << request->params.rootUri->raw_uri; if (!request->params.initializationOptions) { - LOG_S(FATAL) << "Initialization parameters (particularily cacheDirectory) are required"; + LOG_S(FATAL) << "Initialization parameters (particularily " + "cacheDirectory) are required"; exit(1); } @@ -1452,11 +1433,17 @@ bool QueryDbMainLoop( Out_ShowLogMessage out; out.display_type = Out_ShowLogMessage::DisplayType::Show; out.params.type = lsMessageType::Error; - out.params.message = "cquery client (v" + std::to_string(config->clientVersion) + ") and server (v" + std::to_string(kExpectedClientVersion) + ") version mismatch. Please update "; + out.params.message = + "cquery client (v" + std::to_string(config->clientVersion) + + ") and server (v" + std::to_string(kExpectedClientVersion) + + ") version mismatch. Please update "; if (config->clientVersion > kExpectedClientVersion) out.params.message += "the cquery binary."; else - out.params.message += "your extension client (VSIX file). Make sure to uninstall the cquery extension and restart vscode before reinstalling."; + out.params.message += + "your extension client (VSIX file). Make sure to uninstall " + "the cquery extension and restart vscode before " + "reinstalling."; out.Write(std::cout); } @@ -1470,18 +1457,23 @@ bool QueryDbMainLoop( MakeDirectoryRecursive(config->cacheDirectory); // Set project root. - config->projectRoot = NormalizePath(request->params.rootUri->GetPath()); + config->projectRoot = + NormalizePath(request->params.rootUri->GetPath()); EnsureEndsInSlash(config->projectRoot); // Start indexer threads. // Set default indexer count if not specified. if (config->indexerCount == 0) { - config->indexerCount = std::max(std::thread::hardware_concurrency(), 2) - 1; + config->indexerCount = + std::max(std::thread::hardware_concurrency(), 2) - 1; } - std::cerr << "[querydb] Starting " << config->indexerCount << " indexers" << std::endl; + std::cerr << "[querydb] Starting " << config->indexerCount + << " indexers" << std::endl; for (int i = 0; i < config->indexerCount; ++i) { WorkThread::StartThread("indexer" + std::to_string(i), [&]() { - return IndexMain(config, file_consumer_shared, timestamp_manager, import_manager, project, working_files, waiter, queue); + return IndexMain(config, file_consumer_shared, timestamp_manager, + import_manager, project, working_files, waiter, + queue); }); } @@ -1489,49 +1481,64 @@ bool QueryDbMainLoop( // Open up / load the project. project->Load(config->extraClangArguments, project_path); - time.ResetAndPrint("[perf] Loaded compilation entries (" + std::to_string(project->entries.size()) + " files)"); + time.ResetAndPrint("[perf] Loaded compilation entries (" + + std::to_string(project->entries.size()) + + " files)"); - // Start scanning include directories before dispatching project files, because that takes a long time. + // Start scanning include directories before dispatching project + // files, because that takes a long time. include_complete->Rescan(); time.Reset(); - project->ForAllFilteredFiles(config, [&](int i, const Project::Entry& entry) { - //std::cerr << "[" << i << "/" << (project->entries.size() - 1) - // << "] Dispatching index request for file " << entry.filename - // << std::endl; - bool is_interactive = working_files->GetFileByFilename(entry.filename) != nullptr; - queue->index_request.Enqueue(Index_Request(entry.filename, entry.args, is_interactive, nullopt)); - }); + project->ForAllFilteredFiles( + config, [&](int i, const Project::Entry& entry) { + // std::cerr << "[" << i << "/" << (project->entries.size() - 1) + // << "] Dispatching index request for file " << entry.filename + // << std::endl; + bool is_interactive = + working_files->GetFileByFilename(entry.filename) != nullptr; + queue->index_request.Enqueue(Index_Request( + entry.filename, entry.args, is_interactive, nullopt)); + }); // We need to support multiple concurrent index processes. time.ResetAndPrint("[perf] Dispatched initial index requests"); } - // TODO: query request->params.capabilities.textDocument and support only things - // the client supports. + // TODO: query request->params.capabilities.textDocument and support + // only things the client supports. auto response = Out_InitializeResponse(); response.id = request->id; - //response.result.capabilities.textDocumentSync = lsTextDocumentSyncOptions(); - //response.result.capabilities.textDocumentSync->openClose = true; - //response.result.capabilities.textDocumentSync->change = lsTextDocumentSyncKind::Full; - //response.result.capabilities.textDocumentSync->willSave = true; - //response.result.capabilities.textDocumentSync->willSaveWaitUntil = true; - response.result.capabilities.textDocumentSync = lsTextDocumentSyncKind::Incremental; + // response.result.capabilities.textDocumentSync = + // lsTextDocumentSyncOptions(); + // response.result.capabilities.textDocumentSync->openClose = true; + // response.result.capabilities.textDocumentSync->change = + // lsTextDocumentSyncKind::Full; + // response.result.capabilities.textDocumentSync->willSave = true; + // response.result.capabilities.textDocumentSync->willSaveWaitUntil = + // true; + response.result.capabilities.textDocumentSync = + lsTextDocumentSyncKind::Incremental; response.result.capabilities.renameProvider = true; response.result.capabilities.completionProvider = lsCompletionOptions(); - response.result.capabilities.completionProvider->resolveProvider = false; - // vscode doesn't support trigger character sequences, so we use ':' for '::' and '>' for '->'. - // See https://github.com/Microsoft/language-server-protocol/issues/138. - response.result.capabilities.completionProvider->triggerCharacters = { ".", ":", ">", "#" }; + response.result.capabilities.completionProvider->resolveProvider = + false; + // vscode doesn't support trigger character sequences, so we use ':' for + // '::' and '>' for '->'. See + // https://github.com/Microsoft/language-server-protocol/issues/138. + response.result.capabilities.completionProvider->triggerCharacters = { + ".", ":", ">", "#"}; - response.result.capabilities.signatureHelpProvider = lsSignatureHelpOptions(); + response.result.capabilities.signatureHelpProvider = + lsSignatureHelpOptions(); // NOTE: If updating signature help tokens make sure to also update // WorkingFile::FindClosestCallNameInBuffer. - response.result.capabilities.signatureHelpProvider->triggerCharacters = { "(", "," }; + response.result.capabilities.signatureHelpProvider + ->triggerCharacters = {"(", ","}; response.result.capabilities.codeLensProvider = lsCodeLensOptions(); response.result.capabilities.codeLensProvider->resolveProvider = false; @@ -1546,8 +1553,10 @@ bool QueryDbMainLoop( response.result.capabilities.documentSymbolProvider = true; response.result.capabilities.workspaceSymbolProvider = true; - response.result.capabilities.documentLinkProvider = lsDocumentLinkOptions(); - response.result.capabilities.documentLinkProvider->resolveProvider = false; + response.result.capabilities.documentLinkProvider = + lsDocumentLinkOptions(); + response.result.capabilities.documentLinkProvider->resolveProvider = + false; ipc->SendOutMessageToClient(IpcId::Initialize, response); break; @@ -1560,12 +1569,16 @@ bool QueryDbMainLoop( case IpcId::CqueryFreshenIndex: { LOG_S(INFO) << "Freshening " << project->entries.size() << " files"; - project->ForAllFilteredFiles(config, [&](int i, const Project::Entry& entry) { - LOG_S(INFO) << "[" << i << "/" << (project->entries.size() - 1) - << "] Dispatching index request for file " << entry.filename; - bool is_interactive = working_files->GetFileByFilename(entry.filename) != nullptr; - queue->index_request.Enqueue(Index_Request(entry.filename, entry.args, is_interactive, nullopt)); - }); + project->ForAllFilteredFiles( + config, [&](int i, const Project::Entry& entry) { + LOG_S(INFO) << "[" << i << "/" << (project->entries.size() - 1) + << "] Dispatching index request for file " + << entry.filename; + bool is_interactive = + working_files->GetFileByFilename(entry.filename) != nullptr; + queue->index_request.Enqueue(Index_Request( + entry.filename, entry.args, is_interactive, nullopt)); + }); break; } @@ -1573,21 +1586,26 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_CqueryTypeHierarchyTree response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { if (ref.idx.kind == SymbolKind::Type) { - response.result = BuildInheritanceHierarchyForType(db, working_files, QueryTypeId(ref.idx.idx)); + response.result = BuildInheritanceHierarchyForType( + db, working_files, QueryTypeId(ref.idx.idx)); break; } if (ref.idx.kind == SymbolKind::Func) { - response.result = BuildInheritanceHierarchyForFunc(db, working_files, QueryFuncId(ref.idx.idx)); + response.result = BuildInheritanceHierarchyForFunc( + db, working_files, QueryFuncId(ref.idx.idx)); break; } } @@ -1600,17 +1618,21 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_CqueryCallTree response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { if (ref.idx.kind == SymbolKind::Func) { - response.result = BuildInitialCallTree(db, working_files, QueryFuncId(ref.idx.idx)); + response.result = BuildInitialCallTree(db, working_files, + QueryFuncId(ref.idx.idx)); break; } } @@ -1627,7 +1649,8 @@ bool QueryDbMainLoop( auto func_id = db->usr_to_func.find(msg->params.usr); if (func_id != db->usr_to_func.end()) - response.result = BuildExpandCallTree(db, working_files, func_id->second); + response.result = + BuildExpandCallTree(db, working_files, func_id->second); ipc->SendOutMessageToClient(IpcId::CqueryCallTreeExpand, response); break; @@ -1637,18 +1660,23 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_LocationList response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { if (ref.idx.kind == SymbolKind::Type) { optional& type = db->types[ref.idx.idx]; - if (!type) continue; - std::vector locations = ToQueryLocation(db, type->instances); + if (!type) + continue; + std::vector locations = + ToQueryLocation(db, type->instances); response.result = GetLsLocations(db, working_files, locations); } } @@ -1660,21 +1688,28 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_LocationList response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { if (ref.idx.kind == SymbolKind::Func) { optional& func = db->funcs[ref.idx.idx]; - if (!func) continue; - std::vector locations = ToQueryLocation(db, func->callers); - for (QueryFuncRef func_ref : GetCallersForAllBaseFunctions(db, *func)) + if (!func) + continue; + std::vector locations = + ToQueryLocation(db, func->callers); + for (QueryFuncRef func_ref : + GetCallersForAllBaseFunctions(db, *func)) locations.push_back(func_ref.loc); - for (QueryFuncRef func_ref : GetCallersForAllDerivedFunctions(db, *func)) + for (QueryFuncRef func_ref : + GetCallersForAllDerivedFunctions(db, *func)) locations.push_back(func_ref.loc); response.result = GetLsLocations(db, working_files, locations); @@ -1688,27 +1723,36 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_LocationList response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { if (ref.idx.kind == SymbolKind::Type) { optional& type = db->types[ref.idx.idx]; - if (!type) continue; - std::vector locations = ToQueryLocation(db, type->def.parents); + if (!type) + continue; + std::vector locations = + ToQueryLocation(db, type->def.parents); response.result = GetLsLocations(db, working_files, locations); - } - else if (ref.idx.kind == SymbolKind::Func) { + } else if (ref.idx.kind == SymbolKind::Func) { optional& func = db->funcs[ref.idx.idx]; - if (!func) continue; - optional location = GetBaseDefinitionOrDeclarationSpelling(db, *func); - if (!location) continue; - optional ls_loc = GetLsLocation(db, working_files, *location); - if (!ls_loc) continue; + if (!func) + continue; + optional location = + GetBaseDefinitionOrDeclarationSpelling(db, *func); + if (!location) + continue; + optional ls_loc = + GetLsLocation(db, working_files, *location); + if (!ls_loc) + continue; response.result.push_back(*ls_loc); } } @@ -1720,24 +1764,30 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_LocationList response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { if (ref.idx.kind == SymbolKind::Type) { optional& type = db->types[ref.idx.idx]; - if (!type) continue; - std::vector locations = ToQueryLocation(db, type->derived); + if (!type) + continue; + std::vector locations = + ToQueryLocation(db, type->derived); response.result = GetLsLocations(db, working_files, locations); - } - else if (ref.idx.kind == SymbolKind::Func) { + } else if (ref.idx.kind == SymbolKind::Func) { optional& func = db->funcs[ref.idx.idx]; - if (!func) continue; - std::vector locations = ToQueryLocation(db, func->derived); + if (!func) + continue; + std::vector locations = + ToQueryLocation(db, func->derived); response.result = GetLsLocations(db, working_files, locations); } } @@ -1745,15 +1795,6 @@ bool QueryDbMainLoop( break; } - - - - - - - - - case IpcId::TextDocumentDidOpen: { // NOTE: This function blocks code lens. If it starts taking a long time // we will need to find a way to unblock the code lens request. @@ -1762,7 +1803,8 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); std::string path = msg->params.textDocument.uri.GetPath(); WorkingFile* working_file = working_files->OnOpen(msg->params); - optional cached_file_contents = LoadCachedFileContents(config, path); + optional cached_file_contents = + LoadCachedFileContents(config, path); if (cached_file_contents) working_file->SetIndexContent(*cached_file_contents); else @@ -1772,14 +1814,18 @@ bool QueryDbMainLoop( if (cache && !cache->skipped_by_preprocessor.empty()) PublishInactiveLines(working_file, cache->skipped_by_preprocessor); - time.ResetAndPrint("[querydb] Loading cached index file for DidOpen (blocks CodeLens)"); + time.ResetAndPrint( + "[querydb] Loading cached index file for DidOpen (blocks " + "CodeLens)"); include_complete->AddFile(working_file->filename); clang_complete->NotifyView(path); // Submit new index request. - const Project::Entry& entry = project->FindCompilationEntryForFile(path); - queue->index_request.PriorityEnqueue(Index_Request(entry.filename, entry.args, true /*is_interactive*/, nullopt)); + const Project::Entry& entry = + project->FindCompilationEntryForFile(path); + queue->index_request.PriorityEnqueue(Index_Request( + entry.filename, entry.args, true /*is_interactive*/, nullopt)); break; } @@ -1798,7 +1844,8 @@ bool QueryDbMainLoop( // Clear any diagnostics for the file. Out_TextDocumentPublishDiagnostics diag; diag.params.uri = msg->params.textDocument.uri; - IpcManager::instance()->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diag); + IpcManager::instance()->SendOutMessageToClient( + IpcId::TextDocumentPublishDiagnostics, diag); // Remove internal state. working_files->OnClose(msg->params); @@ -1824,7 +1871,8 @@ bool QueryDbMainLoop( // if so, ignore that index response. // TODO: send as priority request Project::Entry entry = project->FindCompilationEntryForFile(path); - queue->index_request.Enqueue(Index_Request(entry.filename, entry.args, true /*is_interactive*/, nullopt)); + queue->index_request.Enqueue(Index_Request( + entry.filename, entry.args, true /*is_interactive*/, nullopt)); clang_complete->NotifySave(path); @@ -1836,18 +1884,22 @@ bool QueryDbMainLoop( QueryFileId file_id; QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file, &file_id)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file, &file_id)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_TextDocumentRename response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { // Found symbol. Return references to rename. std::vector uses = GetUsesOfSymbol(db, ref.idx); - response.result = BuildWorkspaceEdit(db, working_files, uses, msg->params.newName); + response.result = + BuildWorkspaceEdit(db, working_files, uses, msg->params.newName); break; } @@ -1865,7 +1917,8 @@ bool QueryDbMainLoop( // 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 (msg->params.position.line >= 0 && msg->params.position.line < file->all_buffer_lines.size()) + if (msg->params.position.line >= 0 && + msg->params.position.line < file->all_buffer_lines.size()) buffer_line = file->all_buffer_lines[msg->params.position.line]; if (ShouldRunIncludeCompletion(buffer_line)) { @@ -1874,12 +1927,13 @@ bool QueryDbMainLoop( complete_response.result.isIncomplete = false; { - std::unique_lock lock(include_complete->completion_items_mutex, std::defer_lock); + std::unique_lock lock( + include_complete->completion_items_mutex, std::defer_lock); if (include_complete->is_scanning) lock.lock(); complete_response.result.items.assign( - include_complete->completion_items.begin(), - include_complete->completion_items.end()); + include_complete->completion_items.begin(), + include_complete->completion_items.end()); if (lock) lock.unlock(); @@ -1892,88 +1946,119 @@ bool QueryDbMainLoop( } } - LOG_S(INFO) << "[complete] Returning " << complete_response.result.items.size() << " include completions"; + LOG_S(INFO) << "[complete] Returning " + << complete_response.result.items.size() + << " include completions"; FilterCompletionResponse(&complete_response, buffer_line); - ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, complete_response); - } - else { + ipc->SendOutMessageToClient(IpcId::TextDocumentCompletion, + complete_response); + } else { bool is_global_completion = false; std::string existing_completion; if (file) { - msg->params.position = file->FindStableCompletionSource(msg->params.position, &is_global_completion, &existing_completion); + msg->params.position = file->FindStableCompletionSource( + msg->params.position, &is_global_completion, + &existing_completion); } - LOG_S(INFO) << "[complete] Got existing completion " << existing_completion; + LOG_S(INFO) << "[complete] Got existing completion " + << existing_completion; ClangCompleteManager::OnComplete callback = std::bind( - [working_files, global_code_complete_cache, non_global_code_complete_cache, is_global_completion, existing_completion, msg] - (const NonElidedVector& results, bool is_cached_result) { + [working_files, global_code_complete_cache, + non_global_code_complete_cache, is_global_completion, + existing_completion, + msg](const NonElidedVector& results, + bool is_cached_result) { - Out_TextDocumentComplete complete_response; - complete_response.id = msg->id; - complete_response.result.isIncomplete = false; - complete_response.result.items = results; + Out_TextDocumentComplete complete_response; + complete_response.id = msg->id; + complete_response.result.isIncomplete = false; + complete_response.result.items = results; - // Emit completion results. - FilterCompletionResponse(&complete_response, existing_completion); - IpcManager::instance()->SendOutMessageToClient(IpcId::TextDocumentCompletion, complete_response); + // Emit completion results. + FilterCompletionResponse(&complete_response, + existing_completion); + IpcManager::instance()->SendOutMessageToClient( + IpcId::TextDocumentCompletion, complete_response); - // Cache completion results. - if (!is_cached_result) { - std::string path = msg->params.textDocument.uri.GetPath(); - if (is_global_completion) { - global_code_complete_cache->WithLock([&]() { - global_code_complete_cache->cached_path_ = path; - LOG_S(INFO) << "[complete] Updating global_code_complete_cache->cached_results [0]"; - global_code_complete_cache->cached_results_ = results; - LOG_S(INFO) << "[complete] DONE Updating global_code_complete_cache->cached_results [0]"; - }); - } - else { - non_global_code_complete_cache->WithLock([&]() { - non_global_code_complete_cache->cached_path_ = path; - non_global_code_complete_cache->cached_completion_position_ = msg->params.position; - LOG_S(INFO) << "[complete] Updating non_global_code_complete_cache->cached_results [1]"; - non_global_code_complete_cache->cached_results_ = results; - LOG_S(INFO) << "[complete] DONE Updating non_global_code_complete_cache->cached_results [1]"; - }); - } - } - }, std::placeholders::_1, std::placeholders::_2); + // Cache completion results. + if (!is_cached_result) { + std::string path = msg->params.textDocument.uri.GetPath(); + if (is_global_completion) { + global_code_complete_cache->WithLock([&]() { + global_code_complete_cache->cached_path_ = path; + LOG_S(INFO) << "[complete] Updating " + "global_code_complete_cache->cached_" + "results [0]"; + global_code_complete_cache->cached_results_ = results; + LOG_S(INFO) << "[complete] DONE Updating " + "global_code_complete_cache->cached_" + "results [0]"; + }); + } else { + non_global_code_complete_cache->WithLock([&]() { + non_global_code_complete_cache->cached_path_ = path; + non_global_code_complete_cache + ->cached_completion_position_ = msg->params.position; + LOG_S(INFO) << "[complete] Updating " + "non_global_code_complete_cache->cached_" + "results [1]"; + non_global_code_complete_cache->cached_results_ = results; + LOG_S(INFO) << "[complete] DONE Updating " + "non_global_code_complete_cache->cached_" + "results [1]"; + }); + } + } + }, + std::placeholders::_1, std::placeholders::_2); bool is_cache_match = false; global_code_complete_cache->WithLock([&]() { - is_cache_match = is_global_completion && global_code_complete_cache->cached_path_ == path && !global_code_complete_cache->cached_results_.empty(); + is_cache_match = + is_global_completion && + global_code_complete_cache->cached_path_ == path && + !global_code_complete_cache->cached_results_.empty(); }); if (is_cache_match) { - LOG_S(INFO) << "[complete] Early-returning cached global completion results at " << msg->params.position.ToString(); + LOG_S(INFO) << "[complete] Early-returning cached global " + "completion results at " + << msg->params.position.ToString(); ClangCompleteManager::OnComplete freshen_global = - [global_code_complete_cache] - (NonElidedVector results, bool is_cached_result) { + [global_code_complete_cache]( + NonElidedVector results, + bool is_cached_result) { - assert(!is_cached_result); + assert(!is_cached_result); - LOG_S(INFO) << "[complete] Updating global_code_complete_cache->cached_results [2]"; - // note: path is updated in the normal completion handler. - global_code_complete_cache->WithLock([&]() { - global_code_complete_cache->cached_results_ = results; - }); - LOG_S(INFO) << "[complete] DONE Updating global_code_complete_cache->cached_results [2]"; - }; + LOG_S(INFO) << "[complete] Updating " + "global_code_complete_cache->cached_results " + "[2]"; + // note: path is updated in the normal completion handler. + global_code_complete_cache->WithLock([&]() { + global_code_complete_cache->cached_results_ = results; + }); + LOG_S(INFO) << "[complete] DONE Updating " + "global_code_complete_cache->cached_results " + "[2]"; + }; global_code_complete_cache->WithLock([&]() { - callback(global_code_complete_cache->cached_results_, true /*is_cached_result*/); + callback(global_code_complete_cache->cached_results_, + true /*is_cached_result*/); }); clang_complete->CodeComplete(msg->params, freshen_global); - } - else if (non_global_code_complete_cache->IsCacheValid(msg->params)) { - LOG_S(INFO) << "[complete] Using cached completion results at " << msg->params.position.ToString(); + } else if (non_global_code_complete_cache->IsCacheValid( + msg->params)) { + LOG_S(INFO) << "[complete] Using cached completion results at " + << msg->params.position.ToString(); non_global_code_complete_cache->WithLock([&]() { - callback(non_global_code_complete_cache->cached_results_, true /*is_cached_result*/); + callback(non_global_code_complete_cache->cached_results_, + true /*is_cached_result*/); }); - } - else { + } else { clang_complete->CodeComplete(msg->params, callback); } } @@ -1984,77 +2069,87 @@ bool QueryDbMainLoop( case IpcId::TextDocumentSignatureHelp: { auto msg = static_cast(message.get()); lsTextDocumentPositionParams& params = msg->params; - WorkingFile* file = working_files->GetFileByFilename(params.textDocument.uri.GetPath()); + WorkingFile* file = + working_files->GetFileByFilename(params.textDocument.uri.GetPath()); std::string search; int active_param = 0; if (file) { lsPosition completion_position; - search = file->FindClosestCallNameInBuffer(params.position, &active_param, &completion_position); + search = file->FindClosestCallNameInBuffer( + params.position, &active_param, &completion_position); params.position = completion_position; } - //LOG_S(INFO) << "[completion] Returning signatures for " << search; if (search.empty()) break; ClangCompleteManager::OnComplete callback = std::bind( - [signature_cache] - (BaseIpcMessage* message, std::string search, int active_param, const NonElidedVector& results, bool is_cached_result) { - auto msg = static_cast(message); - auto ipc = IpcManager::instance(); + [signature_cache](BaseIpcMessage* message, std::string search, + int active_param, + const NonElidedVector& results, + bool is_cached_result) { + auto msg = static_cast(message); + auto ipc = IpcManager::instance(); - Out_TextDocumentSignatureHelp response; - response.id = msg->id; + Out_TextDocumentSignatureHelp response; + response.id = msg->id; - for (auto& result : results) { - if (result.label != search) - continue; + for (auto& result : results) { + if (result.label != search) + continue; - lsSignatureInformation signature; - signature.label = result.detail; - for (auto& parameter : result.parameters_) { - lsParameterInformation ls_param; - ls_param.label = parameter; - signature.parameters.push_back(ls_param); - } - response.result.signatures.push_back(signature); - } + lsSignatureInformation signature; + signature.label = result.detail; + for (auto& parameter : result.parameters_) { + lsParameterInformation ls_param; + ls_param.label = parameter; + signature.parameters.push_back(ls_param); + } + response.result.signatures.push_back(signature); + } - // Guess the signature the user wants based on available parameter - // count. - response.result.activeSignature = 0; - for (size_t i = 0; i < response.result.signatures.size(); ++i) { - if (active_param < response.result.signatures.size()) { - response.result.activeSignature = (int)i; - break; - } - } + // Guess the signature the user wants based on available parameter + // count. + response.result.activeSignature = 0; + for (size_t i = 0; i < response.result.signatures.size(); ++i) { + if (active_param < response.result.signatures.size()) { + response.result.activeSignature = (int)i; + break; + } + } - // Set signature to what we parsed from the working file. - response.result.activeParameter = active_param; + // Set signature to what we parsed from the working file. + response.result.activeParameter = active_param; - Timer timer; - ipc->SendOutMessageToClient(IpcId::TextDocumentSignatureHelp, response); - timer.ResetAndPrint("[complete] Writing signature help results"); + Timer timer; + ipc->SendOutMessageToClient(IpcId::TextDocumentSignatureHelp, + response); + timer.ResetAndPrint("[complete] Writing signature help results"); - if (!is_cached_result) { - signature_cache->WithLock([&]() { - signature_cache->cached_path_ = msg->params.textDocument.uri.GetPath(); - signature_cache->cached_completion_position_ = msg->params.position; - LOG_S(INFO) << "[complete] Updating signature_cache->cached_results [3]"; - signature_cache->cached_results_ = results; - }); - } + if (!is_cached_result) { + signature_cache->WithLock([&]() { + signature_cache->cached_path_ = + msg->params.textDocument.uri.GetPath(); + signature_cache->cached_completion_position_ = + msg->params.position; + LOG_S(INFO) << "[complete] Updating " + "signature_cache->cached_results [3]"; + signature_cache->cached_results_ = results; + }); + } - delete message; - }, message.release(), search, active_param, std::placeholders::_1, std::placeholders::_2); + delete message; + }, + message.release(), search, active_param, std::placeholders::_1, + std::placeholders::_2); if (signature_cache->IsCacheValid(params)) { - LOG_S(INFO) << "[complete] Using cached completion results at " << params.position.ToString(); + LOG_S(INFO) << "[complete] Using cached completion results at " + << params.position.ToString(); signature_cache->WithLock([&]() { - callback(signature_cache->cached_results_, true /*is_cached_result*/); + callback(signature_cache->cached_results_, + true /*is_cached_result*/); }); - } - else { + } else { clang_complete->CodeComplete(params, std::move(callback)); } @@ -2066,10 +2161,12 @@ bool QueryDbMainLoop( QueryFileId file_id; QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file, &file_id)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file, &file_id)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_TextDocumentDefinition response; response.id = msg->id; @@ -2077,7 +2174,8 @@ bool QueryDbMainLoop( int target_line = msg->params.position.line + 1; int target_column = msg->params.position.character + 1; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { // Found symbol. Return definition. // Special cases which are handled: @@ -2085,12 +2183,14 @@ bool QueryDbMainLoop( // - start at spelling but end at extent for better mouse tooltip // - goto declaration while in definition of recursive type - optional def_loc = GetDefinitionSpellingOfSymbol(db, ref.idx); + optional def_loc = + GetDefinitionSpellingOfSymbol(db, ref.idx); // We use spelling start and extent end because this causes vscode to // highlight the entire definition when previewing / hoving with the // mouse. - optional def_extent = GetDefinitionExtentOfSymbol(db, ref.idx); + optional def_extent = + GetDefinitionExtentOfSymbol(db, ref.idx); if (def_loc && def_extent) def_loc->range.end = def_extent->range.end; @@ -2098,23 +2198,29 @@ bool QueryDbMainLoop( // the declaration if possible. We also want to use declarations if // we're pointing to, ie, a pure virtual function which has no // definition. - if (!def_loc || (def_loc->path == file_id && - def_loc->range.Contains(target_line, target_column))) { + if (!def_loc || + (def_loc->path == file_id && + def_loc->range.Contains(target_line, target_column))) { // Goto declaration. - std::vector declarations = GetDeclarationsOfSymbolForGotoDefinition(db, ref.idx); + std::vector declarations = + GetDeclarationsOfSymbolForGotoDefinition(db, ref.idx); for (auto declaration : declarations) { - optional ls_declaration = GetLsLocation(db, working_files, declaration); + optional ls_declaration = + GetLsLocation(db, working_files, declaration); if (ls_declaration) response.result.push_back(*ls_declaration); } - // We found some declarations. Break so we don't add the definition location. + // We found some declarations. Break so we don't add the definition + // location. if (!response.result.empty()) break; } - if (def_loc) - PushBack(&response.result, GetLsLocation(db, working_files, *def_loc)); + if (def_loc) { + PushBack(&response.result, + GetLsLocation(db, working_files, *def_loc)); + } if (!response.result.empty()) break; @@ -2137,19 +2243,23 @@ bool QueryDbMainLoop( } case IpcId::TextDocumentDocumentHighlight: { - auto msg = static_cast(message.get()); + auto msg = + static_cast(message.get()); QueryFileId file_id; QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file, &file_id)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file, &file_id)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_TextDocumentDocumentHighlight response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { // Found symbol. Return references to highlight. std::vector uses = GetUsesOfSymbol(db, ref.idx); response.result.reserve(uses.size()); @@ -2157,7 +2267,8 @@ bool QueryDbMainLoop( if (use.path != file_id) continue; - optional ls_location = GetLsLocation(db, working_files, use); + optional ls_location = + GetLsLocation(db, working_files, use); if (!ls_location) continue; @@ -2169,7 +2280,8 @@ bool QueryDbMainLoop( break; } - ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentHighlight, response); + ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentHighlight, + response); break; } @@ -2177,17 +2289,21 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_TextDocumentHover response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { // Found symbol. Return hover. - optional ls_range = GetLsRange(working_files->GetFileByFilename(file->def.path), ref.loc.range); + optional ls_range = GetLsRange( + working_files->GetFileByFilename(file->def.path), ref.loc.range); if (!ls_range) continue; @@ -2204,15 +2320,18 @@ bool QueryDbMainLoop( auto msg = static_cast(message.get()); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(file->def.path); + WorkingFile* working_file = + working_files->GetFileByFilename(file->def.path); Out_TextDocumentReferences response; response.id = msg->id; - for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, msg->params.position)) { + for (const SymbolRef& ref : + FindSymbolsAtLocation(working_file, file, msg->params.position)) { optional excluded_declaration; if (!msg->params.context.includeDeclaration) { LOG_S(INFO) << "Excluding declaration in references"; @@ -2223,10 +2342,12 @@ bool QueryDbMainLoop( std::vector uses = GetUsesOfSymbol(db, ref.idx); response.result.reserve(uses.size()); for (const QueryLocation& use : uses) { - if (excluded_declaration.has_value() && use == *excluded_declaration) + if (excluded_declaration.has_value() && + use == *excluded_declaration) continue; - optional ls_location = GetLsLocation(db, working_files, use); + optional ls_location = + GetLsLocation(db, working_files, use); if (ls_location) response.result.push_back(*ls_location); } @@ -2244,23 +2365,26 @@ bool QueryDbMainLoop( response.id = msg->id; QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; - for (SymbolRef ref : file->def.outline) { - optional info = GetSymbolInfo(db, working_files, ref.idx); + optional info = + GetSymbolInfo(db, working_files, ref.idx); if (!info) continue; - optional location = GetLsLocation(db, working_files, ref.loc); + optional location = + GetLsLocation(db, working_files, ref.loc); if (!location) continue; info->location = *location; response.result.push_back(*info); } - ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentSymbol, response); + ipc->SendOutMessageToClient(IpcId::TextDocumentDocumentSymbol, + response); break; } @@ -2272,23 +2396,29 @@ bool QueryDbMainLoop( if (config->showDocumentLinksOnIncludes) { QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, + msg->params.textDocument.uri.GetPath(), &file)) break; - WorkingFile* working_file = working_files->GetFileByFilename(msg->params.textDocument.uri.GetPath()); + WorkingFile* working_file = working_files->GetFileByFilename( + msg->params.textDocument.uri.GetPath()); if (!working_file) { - LOG_S(INFO) << "Unable to find working file " << msg->params.textDocument.uri.GetPath(); + LOG_S(INFO) << "Unable to find working file " + << msg->params.textDocument.uri.GetPath(); break; } for (const IndexInclude& include : file->def.includes) { optional buffer_line; - optional buffer_line_content = working_file->GetBufferLineContentFromIndexLine(include.line, &buffer_line); + optional buffer_line_content = + working_file->GetBufferLineContentFromIndexLine(include.line, + &buffer_line); if (!buffer_line || !buffer_line_content) continue; // Subtract 1 from line because querydb stores 1-based lines but // vscode expects 0-based lines. - optional between_quotes = ExtractQuotedRange(*buffer_line - 1, *buffer_line_content); + optional between_quotes = + ExtractQuotedRange(*buffer_line - 1, *buffer_line_content); if (!between_quotes) continue; @@ -2318,13 +2448,16 @@ bool QueryDbMainLoop( QueryFileId file_id; QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file, &file_id)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file, &file_id)) break; - WorkingFile* working_file = working_files->GetFileByFilename(msg->params.textDocument.uri.GetPath()); + WorkingFile* working_file = working_files->GetFileByFilename( + msg->params.textDocument.uri.GetPath()); if (!working_file) { // TODO: send error response. - LOG_S(INFO) << "[error] textDocument/codeAction could not find working file"; + LOG_S(INFO) + << "[error] textDocument/codeAction could not find working file"; break; } @@ -2341,7 +2474,8 @@ bool QueryDbMainLoop( optional impl_uri; optional impl_file_id; - std::vector syms = FindSymbolsAtLocation(working_file, file, msg->params.range.start); + std::vector syms = + FindSymbolsAtLocation(working_file, file, msg->params.range.start); for (SymbolRef sym : syms) { switch (sym.idx.kind) { case SymbolKind::Type: { @@ -2359,8 +2493,11 @@ bool QueryDbMainLoop( if (!func_def || func_def->def.definition_extent) continue; - EnsureImplFile(db, file_id, impl_uri /*out*/, impl_file_id /*out*/); - optional edit = BuildAutoImplementForFunction(db, working_files, working_file, default_line, file_id, *impl_file_id, *func_def); + EnsureImplFile(db, file_id, impl_uri /*out*/, + impl_file_id /*out*/); + optional edit = BuildAutoImplementForFunction( + db, working_files, working_file, default_line, file_id, + *impl_file_id, *func_def); if (!edit) continue; @@ -2371,22 +2508,25 @@ bool QueryDbMainLoop( // with foo()\n\n\n\nfoo(), we want foo()\n\nfoo()\n\n // if (!command.arguments.edits.empty() && - command.arguments.edits[command.arguments.edits.size() - 1].range.end.line == edit->range.start.line) { - command.arguments.edits[command.arguments.edits.size() - 1].newText += edit->newText; - } - else { + command.arguments.edits[command.arguments.edits.size() - 1] + .range.end.line == edit->range.start.line) { + command.arguments.edits[command.arguments.edits.size() - 1] + .newText += edit->newText; + } else { command.arguments.edits.push_back(*edit); } } if (command.arguments.edits.empty()) break; - // If we're inserting at the end of the document, put a newline before the insertion. + // If we're inserting at the end of the document, put a newline + // before the insertion. if (command.arguments.edits[0].range.start.line >= default_line) command.arguments.edits[0].newText.insert(0, "\n"); command.arguments.textDocumentUri = *impl_uri; - command.title = "Auto-Implement " + std::to_string(num_edits) + " methods on " + type->def.short_name; + command.title = "Auto-Implement " + std::to_string(num_edits) + + " methods on " + type->def.short_name; command.command = "cquery._autoImplement"; response.result.push_back(command); break; @@ -2397,18 +2537,22 @@ bool QueryDbMainLoop( if (!func || func->def.definition_extent) break; - EnsureImplFile(db, file_id, impl_uri /*out*/, impl_file_id /*out*/); + EnsureImplFile(db, file_id, impl_uri /*out*/, + impl_file_id /*out*/); // Get implementation file. Out_TextDocumentCodeAction::Command command; command.title = "Auto-Implement " + func->def.short_name; command.command = "cquery._autoImplement"; command.arguments.textDocumentUri = *impl_uri; - optional edit = BuildAutoImplementForFunction(db, working_files, working_file, default_line, file_id, *impl_file_id, *func); + optional edit = BuildAutoImplementForFunction( + db, working_files, working_file, default_line, file_id, + *impl_file_id, *func); if (!edit) break; - // If we're inserting at the end of the document, put a newline before the insertion. + // If we're inserting at the end of the document, put a newline + // before the insertion. if (edit->range.start.line >= default_line) edit->newText.insert(0, "\n"); command.arguments.edits.push_back(*edit); @@ -2425,9 +2569,8 @@ bool QueryDbMainLoop( } std::vector diagnostics; - working_files->DoAction([&]() { - diagnostics = working_file->diagnostics_; - }); + working_files->DoAction( + [&]() { diagnostics = working_file->diagnostics_; }); for (lsDiagnostic& diag : diagnostics) { if (diag.range.start.line != msg->params.range.start.line) continue; @@ -2435,21 +2578,24 @@ bool QueryDbMainLoop( // For error diagnostics, provide an action to resolve an include. // TODO: find a way to index diagnostic contents so line numbers // don't get mismatched when actively editing a file. - std::string include_query = LexWordAroundPos(diag.range.start, working_file->buffer_content); - if (diag.severity == lsDiagnosticSeverity::Error && !include_query.empty()) { + std::string include_query = + LexWordAroundPos(diag.range.start, working_file->buffer_content); + if (diag.severity == lsDiagnosticSeverity::Error && + !include_query.empty()) { const size_t kMaxResults = 20; - std::unordered_set include_absolute_paths; // Find include candidate strings. for (int i = 0; i < db->detailed_names.size(); ++i) { if (include_absolute_paths.size() > kMaxResults) break; - if (db->detailed_names[i].find(include_query) == std::string::npos) + if (db->detailed_names[i].find(include_query) == + std::string::npos) continue; - optional decl_file_id = GetDeclarationFileForSymbol(db, db->symbols[i]); + optional decl_file_id = + GetDeclarationFileForSymbol(db, db->symbols[i]); if (!decl_file_id) continue; @@ -2465,7 +2611,8 @@ bool QueryDbMainLoop( include_insert_strings.reserve(include_absolute_paths.size()); for (const std::string& path : include_absolute_paths) { - optional item = include_complete->FindCompletionItemForAbsolutePath(path); + optional item = + include_complete->FindCompletionItemForAbsolutePath(path); if (!item) continue; if (item->textEdit) @@ -2473,7 +2620,9 @@ bool QueryDbMainLoop( else if (!item->insertText.empty()) include_insert_strings.insert(item->insertText); else - assert(false && "unable to determine insert string for include completion item"); + assert(false && + "unable to determine insert string for include " + "completion item"); } // Build code action. @@ -2481,9 +2630,11 @@ bool QueryDbMainLoop( Out_TextDocumentCodeAction::Command command; // Build edits. - for (const std::string& include_insert_string : include_insert_strings) { + for (const std::string& include_insert_string : + include_insert_strings) { lsTextEdit edit; - optional include_line = FindIncludeLine(working_file->all_buffer_lines, include_insert_string); + optional include_line = FindIncludeLine( + working_file->all_buffer_lines, include_insert_string); if (!include_line) continue; @@ -2497,7 +2648,9 @@ bool QueryDbMainLoop( if (include_insert_strings.size() == 1) command.title = "Insert " + *include_insert_strings.begin(); else - command.title = "Pick one of " + std::to_string(command.arguments.edits.size()) + " includes to insert"; + command.title = "Pick one of " + + std::to_string(command.arguments.edits.size()) + + " includes to insert"; command.command = "cquery._insertInclude"; command.arguments.textDocumentUri = msg->params.textDocument.uri; response.result.push_back(command); @@ -2533,7 +2686,8 @@ bool QueryDbMainLoop( clang_complete->NotifyView(path); QueryFile* file; - if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), &file)) + if (!FindFileOrFail(db, msg->id, msg->params.textDocument.uri.GetPath(), + &file)) break; CommonCodeLensParams common; @@ -2548,81 +2702,110 @@ bool QueryDbMainLoop( SymbolIdx symbol = ref.idx; switch (symbol.kind) { - case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (!type) - continue; - AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), type->uses, type->def.definition_spelling, true /*force_display*/); - AddCodeLens("derived", "derived", &common, ref.loc.OffsetStartColumn(1), ToQueryLocation(db, type->derived), nullopt, false /*force_display*/); - AddCodeLens("var", "vars", &common, ref.loc.OffsetStartColumn(2), ToQueryLocation(db, type->instances), nullopt, false /*force_display*/); - break; - } - case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (!func) - continue; - - int16_t offset = 0; - - std::vector base_callers = GetCallersForAllBaseFunctions(db, *func); - std::vector derived_callers = GetCallersForAllDerivedFunctions(db, *func); - if (base_callers.empty() && derived_callers.empty()) { - AddCodeLens("call", "calls", &common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func->callers), nullopt, true /*force_display*/); - } - else { - AddCodeLens("direct call", "direct calls", &common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func->callers), nullopt, false /*force_display*/); - if (!base_callers.empty()) - AddCodeLens("base call", "base calls", &common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, base_callers), nullopt, false /*force_display*/); - if (!derived_callers.empty()) - AddCodeLens("derived call", "derived calls", &common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, derived_callers), nullopt, false /*force_display*/); + case SymbolKind::Type: { + optional& type = db->types[symbol.idx]; + if (!type) + continue; + AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), + type->uses, type->def.definition_spelling, + true /*force_display*/); + AddCodeLens("derived", "derived", &common, + ref.loc.OffsetStartColumn(1), + ToQueryLocation(db, type->derived), nullopt, + false /*force_display*/); + AddCodeLens("var", "vars", &common, ref.loc.OffsetStartColumn(2), + ToQueryLocation(db, type->instances), nullopt, + false /*force_display*/); + break; } + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (!func) + continue; - AddCodeLens("derived", "derived", &common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func->derived), nullopt, false /*force_display*/); + int16_t offset = 0; - // "Base" - optional base_loc = GetBaseDefinitionOrDeclarationSpelling(db, *func); - if (base_loc) { - optional ls_base = GetLsLocation(db, working_files, *base_loc); - if (ls_base) { - optional range = GetLsRange(common.working_file, ref.loc.range); - if (range) { - TCodeLens code_lens; - code_lens.range = *range; - code_lens.range.start.character += offset++; - code_lens.command = lsCommand(); - code_lens.command->title = "Base"; - code_lens.command->command = "cquery.goto"; - code_lens.command->arguments.uri = ls_base->uri; - code_lens.command->arguments.position = ls_base->range.start; - response.result.push_back(code_lens); + std::vector base_callers = + GetCallersForAllBaseFunctions(db, *func); + std::vector derived_callers = + GetCallersForAllDerivedFunctions(db, *func); + if (base_callers.empty() && derived_callers.empty()) { + AddCodeLens("call", "calls", &common, + ref.loc.OffsetStartColumn(offset++), + ToQueryLocation(db, func->callers), nullopt, + true /*force_display*/); + } else { + AddCodeLens("direct call", "direct calls", &common, + ref.loc.OffsetStartColumn(offset++), + ToQueryLocation(db, func->callers), nullopt, + false /*force_display*/); + if (!base_callers.empty()) + AddCodeLens("base call", "base calls", &common, + ref.loc.OffsetStartColumn(offset++), + ToQueryLocation(db, base_callers), nullopt, + false /*force_display*/); + if (!derived_callers.empty()) + AddCodeLens("derived call", "derived calls", &common, + ref.loc.OffsetStartColumn(offset++), + ToQueryLocation(db, derived_callers), nullopt, + false /*force_display*/); + } + + AddCodeLens("derived", "derived", &common, + ref.loc.OffsetStartColumn(offset++), + ToQueryLocation(db, func->derived), nullopt, + false /*force_display*/); + + // "Base" + optional base_loc = + GetBaseDefinitionOrDeclarationSpelling(db, *func); + if (base_loc) { + optional ls_base = + GetLsLocation(db, working_files, *base_loc); + if (ls_base) { + optional range = + GetLsRange(common.working_file, ref.loc.range); + if (range) { + TCodeLens code_lens; + code_lens.range = *range; + code_lens.range.start.character += offset++; + code_lens.command = lsCommand(); + code_lens.command->title = "Base"; + code_lens.command->command = "cquery.goto"; + code_lens.command->arguments.uri = ls_base->uri; + code_lens.command->arguments.position = + ls_base->range.start; + response.result.push_back(code_lens); + } } } + + break; } + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (!var) + continue; - break; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (!var) - continue; + if (var->def.is_local && !config->codeLensOnLocalVariables) + continue; - if (var->def.is_local && !config->codeLensOnLocalVariables) - continue; + bool force_display = true; + // Do not show 0 refs on macro with no uses, as it is most likely + // a header guard. + if (var->def.is_macro) + force_display = false; - bool force_display = true; - // Do not show 0 refs on macro with no uses, as it is most likely a - // header guard. - if (var->def.is_macro) - force_display = false; - - AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), var->uses, var->def.definition_spelling, force_display); - break; - } - case SymbolKind::File: - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } + AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), + var->uses, var->def.definition_spelling, + force_display); + break; + } + case SymbolKind::File: + case SymbolKind::Invalid: { + assert(false && "unexpected"); + break; + } }; } @@ -2631,15 +2814,16 @@ bool QueryDbMainLoop( } case IpcId::WorkspaceSymbol: { - // TODO: implement fuzzy search, see https://github.com/junegunn/fzf/blob/master/src/matcher.go for inspiration + // TODO: implement fuzzy search, see + // https://github.com/junegunn/fzf/blob/master/src/matcher.go for + // inspiration auto msg = static_cast(message.get()); Out_WorkspaceSymbol response; response.id = msg->id; - LOG_S(INFO) << "[querydb] Considering " << db->detailed_names.size() - << " candidates for query " << msg->params.query; + << " candidates for query " << msg->params.query; std::string query = msg->params.query; @@ -2652,7 +2836,8 @@ bool QueryDbMainLoop( if (!inserted_results.insert(db->detailed_names[i]).second) continue; - InsertSymbolIntoResult(db, working_files, db->symbols[i], &response.result); + InsertSymbolIntoResult(db, working_files, db->symbols[i], + &response.result); if (response.result.size() >= config->maxWorkspaceSearchResults) break; } @@ -2665,25 +2850,25 @@ bool QueryDbMainLoop( if (!inserted_results.insert(db->detailed_names[i]).second) continue; - InsertSymbolIntoResult(db, working_files, db->symbols[i], &response.result); + InsertSymbolIntoResult(db, working_files, db->symbols[i], + &response.result); if (response.result.size() >= config->maxWorkspaceSearchResults) break; } } } - LOG_S(INFO) << "[querydb] Found " << response.result.size() << " results for query " << query; + LOG_S(INFO) << "[querydb] Found " << response.result.size() + << " results for query " << query; ipc->SendOutMessageToClient(IpcId::WorkspaceSymbol, response); break; } case IpcId::CqueryIndexFile: { auto msg = static_cast(message.get()); - queue->index_request.Enqueue(Index_Request( - NormalizePath(msg->params.path), - msg->params.args, - msg->params.is_interactive, - msg->params.contents)); + queue->index_request.Enqueue( + Index_Request(NormalizePath(msg->params.path), msg->params.args, + msg->params.is_interactive, msg->params.contents)); break; } @@ -2694,7 +2879,8 @@ bool QueryDbMainLoop( bool has_work = false; has_work |= import_manager->HasActiveQuerydbImports(); has_work |= queue->HasWork(); - has_work |= QueryDb_ImportMain(config, db, import_manager, queue, working_files); + has_work |= QueryDb_ImportMain(config, db, import_manager, queue, + working_files); if (!has_work) ++idle_count; else @@ -2716,14 +2902,15 @@ bool QueryDbMainLoop( } default: { - LOG_S(INFO) << "[querydb] Unhandled IPC message " << IpcIdToString(message->method_id); + LOG_S(INFO) << "[querydb] Unhandled IPC message " + << IpcIdToString(message->method_id); exit(1); } } } - // TODO: consider rate-limiting and checking for IPC messages so we don't block - // requests / we can serve partial requests. + // TODO: consider rate-limiting and checking for IPC messages so we don't + // block requests / we can serve partial requests. if (QueryDb_ImportMain(config, db, import_manager, queue, working_files)) did_work = true; @@ -2731,13 +2918,17 @@ bool QueryDbMainLoop( return did_work; } -void RunQueryDbThread(const std::string& bin_name, Config* config, MultiQueueWaiter* waiter, QueueManager* queue) { +void RunQueryDbThread(const std::string& bin_name, + Config* config, + MultiQueueWaiter* waiter, + QueueManager* queue) { bool exit_when_idle = false; Project project; WorkingFiles working_files; ClangCompleteManager clang_complete( - config, &project, &working_files, - std::bind(&EmitDiagnostics, &working_files, std::placeholders::_1, std::placeholders::_2)); + config, &project, &working_files, + std::bind(&EmitDiagnostics, &working_files, std::placeholders::_1, + std::placeholders::_2)); IncludeComplete include_complete(config, &project); auto global_code_complete_cache = MakeUnique(); auto non_global_code_complete_cache = MakeUnique(); @@ -2751,9 +2942,11 @@ void RunQueryDbThread(const std::string& bin_name, Config* config, MultiQueueWai QueryDatabase db; while (true) { bool did_work = QueryDbMainLoop( - config, &db, &exit_when_idle, waiter, queue, - &project, &file_consumer_shared, &import_manager, ×tamp_manager, &working_files, - &clang_complete, &include_complete, global_code_complete_cache.get(), non_global_code_complete_cache.get(), signature_cache.get()); + config, &db, &exit_when_idle, waiter, queue, &project, + &file_consumer_shared, &import_manager, ×tamp_manager, + &working_files, &clang_complete, &include_complete, + global_code_complete_cache.get(), non_global_code_complete_cache.get(), + signature_cache.get()); // No more work left and exit request. Exit. if (!did_work && exit_when_idle && WorkThread::num_active_threads == 0) @@ -2763,11 +2956,8 @@ void RunQueryDbThread(const std::string& bin_name, Config* config, MultiQueueWai FreeUnusedMemory(); if (!did_work) { - waiter->Wait({ - IpcManager::instance()->threaded_queue_for_server_.get(), - &queue->do_id_map, - &queue->on_indexed - }); + waiter->Wait({IpcManager::instance()->threaded_queue_for_server_.get(), + &queue->do_id_map, &queue->on_indexed}); } } } @@ -2840,12 +3030,13 @@ void RunQueryDbThread(const std::string& bin_name, Config* config, MultiQueueWai // blocks. // // |ipc| is connected to a server. -void LaunchStdinLoop(Config* config, std::unordered_map* request_times) { - +void LaunchStdinLoop(Config* config, + std::unordered_map* request_times) { WorkThread::StartThread("stdin", [config, request_times]() { IpcManager* ipc = IpcManager::instance(); - std::unique_ptr message = MessageRegistry::instance()->ReadMessageFromStdin(); + std::unique_ptr message = + MessageRegistry::instance()->ReadMessageFromStdin(); // Message parsing can fail if we don't recognize the method. if (!message) @@ -2853,67 +3044,69 @@ void LaunchStdinLoop(Config* config, std::unordered_map* request_t (*request_times)[message->method_id] = Timer(); - //std::cerr << "[stdin] Got message " << IpcIdToString(message->method_id) << std::endl; + // std::cerr << "[stdin] Got message " << IpcIdToString(message->method_id) + // << std::endl; switch (message->method_id) { - case IpcId::Initialized: { - // TODO: don't send output until we get this notification - break; - } + case IpcId::Initialized: { + // TODO: don't send output until we get this notification + break; + } - case IpcId::CancelRequest: { - // TODO: support cancellation - break; - } + case IpcId::CancelRequest: { + // TODO: support cancellation + break; + } - case IpcId::Exit: { - exit(0); - break; - } + case IpcId::Exit: { + exit(0); + break; + } - case IpcId::CqueryExitWhenIdle: { - // querydb needs to know to exit when idle. We return out of the stdin - // loop to exit the thread. If we keep parsing input stdin is likely - // closed so cquery will exit. - LOG_S(INFO) << "cquery will exit when all threads are idle"; - ipc->SendMessage(IpcManager::Destination::Server, std::move(message)); - return WorkThread::Result::ExitThread; - } + case IpcId::CqueryExitWhenIdle: { + // querydb needs to know to exit when idle. We return out of the stdin + // loop to exit the thread. If we keep parsing input stdin is likely + // closed so cquery will exit. + LOG_S(INFO) << "cquery will exit when all threads are idle"; + ipc->SendMessage(IpcManager::Destination::Server, std::move(message)); + return WorkThread::Result::ExitThread; + } - case IpcId::Initialize: - case IpcId::TextDocumentDidOpen: - case IpcId::TextDocumentDidChange: - case IpcId::TextDocumentDidClose: - case IpcId::TextDocumentDidSave: - case IpcId::TextDocumentRename: - case IpcId::TextDocumentCompletion: - case IpcId::TextDocumentSignatureHelp: - case IpcId::TextDocumentDefinition: - case IpcId::TextDocumentDocumentHighlight: - case IpcId::TextDocumentHover: - case IpcId::TextDocumentReferences: - case IpcId::TextDocumentDocumentSymbol: - case IpcId::TextDocumentDocumentLink: - case IpcId::TextDocumentCodeAction: - case IpcId::TextDocumentCodeLens: - case IpcId::WorkspaceSymbol: - case IpcId::CqueryFreshenIndex: - case IpcId::CqueryTypeHierarchyTree: - case IpcId::CqueryCallTreeInitial: - case IpcId::CqueryCallTreeExpand: - case IpcId::CqueryVars: - case IpcId::CqueryCallers: - case IpcId::CqueryBase: - case IpcId::CqueryDerived: - case IpcId::CqueryIndexFile: - case IpcId::CqueryQueryDbWaitForIdleIndexer: { - ipc->SendMessage(IpcManager::Destination::Server, std::move(message)); - break; - } + case IpcId::Initialize: + case IpcId::TextDocumentDidOpen: + case IpcId::TextDocumentDidChange: + case IpcId::TextDocumentDidClose: + case IpcId::TextDocumentDidSave: + case IpcId::TextDocumentRename: + case IpcId::TextDocumentCompletion: + case IpcId::TextDocumentSignatureHelp: + case IpcId::TextDocumentDefinition: + case IpcId::TextDocumentDocumentHighlight: + case IpcId::TextDocumentHover: + case IpcId::TextDocumentReferences: + case IpcId::TextDocumentDocumentSymbol: + case IpcId::TextDocumentDocumentLink: + case IpcId::TextDocumentCodeAction: + case IpcId::TextDocumentCodeLens: + case IpcId::WorkspaceSymbol: + case IpcId::CqueryFreshenIndex: + case IpcId::CqueryTypeHierarchyTree: + case IpcId::CqueryCallTreeInitial: + case IpcId::CqueryCallTreeExpand: + case IpcId::CqueryVars: + case IpcId::CqueryCallers: + case IpcId::CqueryBase: + case IpcId::CqueryDerived: + case IpcId::CqueryIndexFile: + case IpcId::CqueryQueryDbWaitForIdleIndexer: { + ipc->SendMessage(IpcManager::Destination::Server, std::move(message)); + break; + } - default: { - std::cerr << "[stdin] Unhandled IPC message " << IpcIdToString(message->method_id) << std::endl; - exit(1); - } + default: { + std::cerr << "[stdin] Unhandled IPC message " + << IpcIdToString(message->method_id) << std::endl; + exit(1); + } } return WorkThread::Result::MoreWork; @@ -2965,18 +3158,23 @@ void LaunchStdinLoop(Config* config, std::unordered_map* request_t -void LaunchStdoutThread(std::unordered_map* request_times, MultiQueueWaiter* waiter, QueueManager* queue) { +void LaunchStdoutThread(std::unordered_map* request_times, + MultiQueueWaiter* waiter, + QueueManager* queue) { WorkThread::StartThread("stdout", [=]() { IpcManager* ipc = IpcManager::instance(); - std::vector> messages = ipc->GetMessages(IpcManager::Destination::Client); + std::vector> messages = + ipc->GetMessages(IpcManager::Destination::Client); if (messages.empty()) { - waiter->Wait({ ipc->threaded_queue_for_client_.get() }); - return queue->HasWork() ? WorkThread::Result::MoreWork : WorkThread::Result::NoWork; + waiter->Wait({ipc->threaded_queue_for_client_.get()}); + return queue->HasWork() ? WorkThread::Result::MoreWork + : WorkThread::Result::NoWork; } for (auto& message : messages) { - //std::cerr << "[stdout] Processing message " << IpcIdToString(message->method_id) << std::endl; + // std::cerr << "[stdout] Processing message " << + // IpcIdToString(message->method_id) << std::endl; switch (message->method_id) { case IpcId::Cout: { @@ -2984,7 +3182,8 @@ void LaunchStdoutThread(std::unordered_map* request_times, MultiQu if (ShouldDisplayIpcTiming(msg->original_ipc_id)) { Timer time = (*request_times)[msg->original_ipc_id]; - time.ResetAndPrint("[e2e] Running " + std::string(IpcIdToString(msg->original_ipc_id))); + time.ResetAndPrint("[e2e] Running " + std::string(IpcIdToString( + msg->original_ipc_id))); } std::cout << msg->content; @@ -2993,7 +3192,8 @@ void LaunchStdoutThread(std::unordered_map* request_times, MultiQu } default: { - std::cerr << "[stdout] Unhandled IPC message " << IpcIdToString(message->method_id) << std::endl; + std::cerr << "[stdout] Unhandled IPC message " + << IpcIdToString(message->method_id) << std::endl; exit(1); } } @@ -3003,7 +3203,9 @@ void LaunchStdoutThread(std::unordered_map* request_times, MultiQu }); } -void LanguageServerMain(const std::string& bin_name, Config* config, MultiQueueWaiter* waiter) { +void LanguageServerMain(const std::string& bin_name, + Config* config, + MultiQueueWaiter* waiter) { QueueManager queue(waiter); std::unordered_map request_times; @@ -3067,11 +3269,6 @@ void LanguageServerMain(const std::string& bin_name, Config* config, MultiQueueW -// What's the plan? -// -// - start up a separate process for indexing -// - send file paths to it to index raw compile_commands.json, it can reparse as needed -// - int main(int argc, char** argv) { loguru::init(argc, argv); @@ -3082,10 +3279,10 @@ int main(int argc, char** argv) { MultiQueueWaiter waiter; IpcManager::CreateInstance(&waiter); - //bool loop = true; - //while (loop) + // bool loop = true; + // while (loop) // std::this_thread::sleep_for(std::chrono::milliseconds(10)); - //std::this_thread::sleep_for(std::chrono::seconds(10)); + // std::this_thread::sleep_for(std::chrono::seconds(10)); PlatformInit(); IndexInit(); @@ -3093,7 +3290,7 @@ int main(int argc, char** argv) { RegisterMessageTypes(); std::unordered_map options = - ParseOptions(argc, argv); + ParseOptions(argc, argv); if (HasOption(options, "--test")) { doctest::Context context; @@ -3108,21 +3305,20 @@ int main(int argc, char** argv) { /* for (int i = 0; i < 1; ++i) { std::this_thread::sleep_for(std::chrono::seconds(5)); - std::cerr << "[POST] Memory usage: " << GetProcessMemoryUsedInMb() << "mb" << std::endl; + std::cerr << "[POST] Memory usage: " << GetProcessMemoryUsedInMb() << "mb" + << std::endl; } */ std::cerr << std::endl << "[Enter] to exit" << std::endl; std::cin.get(); return 0; - } - else if (HasOption(options, "--language-server")) { - //std::cerr << "Running language server" << std::endl; + } else if (HasOption(options, "--language-server")) { + // std::cerr << "Running language server" << std::endl; Config config; LanguageServerMain(argv[0], &config, &waiter); return 0; - } - else { + } else { std::cout << R"help(cquery help: cquery is a low-latency C++ language server. @@ -3150,8 +3346,6 @@ int main(int argc, char** argv) { } } - - TEST_SUITE("LexFunctionDeclaration"); TEST_CASE("simple") { @@ -3160,11 +3354,13 @@ TEST_CASE("simple") { std::string insert_text; int newlines_after_name = 0; - LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, + &newlines_after_name); REQUIRE(insert_text == "void Foo() {\n}"); REQUIRE(newlines_after_name == 0); - LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), + &insert_text, &newlines_after_name); REQUIRE(insert_text == "void Type::Foo() {\n}"); REQUIRE(newlines_after_name == 0); } @@ -3175,7 +3371,8 @@ TEST_CASE("ctor") { std::string insert_text; int newlines_after_name = 0; - LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), + &insert_text, &newlines_after_name); REQUIRE(insert_text == "Foo::Foo() {\n}"); REQUIRE(newlines_after_name == 0); } @@ -3186,7 +3383,8 @@ TEST_CASE("dtor") { std::string insert_text; int newlines_after_name = 0; - LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), + &insert_text, &newlines_after_name); REQUIRE(insert_text == "Foo::~Foo() {\n}"); REQUIRE(newlines_after_name == 0); } @@ -3197,11 +3395,13 @@ TEST_CASE("complex return type") { std::string insert_text; int newlines_after_name = 0; - LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, + &newlines_after_name); REQUIRE(insert_text == "std::vector Foo() {\n}"); REQUIRE(newlines_after_name == 0); - LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), + &insert_text, &newlines_after_name); REQUIRE(insert_text == "std::vector Type::Foo() {\n}"); REQUIRE(newlines_after_name == 0); } @@ -3212,11 +3412,13 @@ TEST_CASE("extra complex return type") { std::string insert_text; int newlines_after_name = 0; - LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, + &newlines_after_name); REQUIRE(insert_text == "std::function < int() > \n Foo() {\n}"); REQUIRE(newlines_after_name == 0); - LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), + &insert_text, &newlines_after_name); REQUIRE(insert_text == "std::function < int() > \n Type::Foo() {\n}"); REQUIRE(newlines_after_name == 0); } @@ -3227,19 +3429,19 @@ TEST_CASE("parameters") { std::string insert_text; int newlines_after_name = 0; - LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, + &newlines_after_name); REQUIRE(insert_text == "void Foo(int a,\n\n int b) {\n}"); REQUIRE(newlines_after_name == 2); - LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), &insert_text, &newlines_after_name); + LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), + &insert_text, &newlines_after_name); REQUIRE(insert_text == "void Type::Foo(int a,\n\n int b) {\n}"); REQUIRE(newlines_after_name == 2); } TEST_SUITE_END(); - - TEST_SUITE("LexWordAroundPos"); TEST_CASE("edges") { @@ -3277,14 +3479,12 @@ TEST_CASE("dot, dash, colon are skipped") { TEST_SUITE_END(); - - TEST_SUITE("FindIncludeLine"); TEST_CASE("in document") { std::vector lines = { - "#include ", // 0 - "#include " // 1 + "#include ", // 0 + "#include " // 1 }; REQUIRE(FindIncludeLine(lines, "#include ") == nullopt); @@ -3292,8 +3492,8 @@ TEST_CASE("in document") { TEST_CASE("insert before") { std::vector lines = { - "#include ", // 0 - "#include " // 1 + "#include ", // 0 + "#include " // 1 }; REQUIRE(FindIncludeLine(lines, "#include ") == 0); @@ -3301,8 +3501,8 @@ TEST_CASE("insert before") { TEST_CASE("insert middle") { std::vector lines = { - "#include ", // 0 - "#include " // 1 + "#include ", // 0 + "#include " // 1 }; REQUIRE(FindIncludeLine(lines, "#include ") == 1); @@ -3310,9 +3510,9 @@ TEST_CASE("insert middle") { TEST_CASE("insert after") { std::vector lines = { - "#include ", // 0 - "#include ", // 1 - "", // 2 + "#include ", // 0 + "#include ", // 1 + "", // 2 }; REQUIRE(FindIncludeLine(lines, "#include ") == 2); @@ -3320,14 +3520,14 @@ TEST_CASE("insert after") { TEST_CASE("ignore header") { std::vector lines = { - "// FOOBAR", // 0 - "// FOOBAR", // 1 - "// FOOBAR", // 2 - "// FOOBAR", // 3 - "", // 4 - "#include ", // 5 - "#include ", // 6 - "", // 7 + "// FOOBAR", // 0 + "// FOOBAR", // 1 + "// FOOBAR", // 2 + "// FOOBAR", // 3 + "", // 4 + "#include ", // 5 + "#include ", // 6 + "", // 7 }; REQUIRE(FindIncludeLine(lines, "#include ") == 5); diff --git a/src/config.h b/src/config.h index 94003840..b0024c11 100644 --- a/src/config.h +++ b/src/config.h @@ -17,7 +17,7 @@ struct Config { // If true, project paths that were skipped by the whitelist/blacklist will // be logged. bool logSkippedPathsForIndex = false; - + // Maximum workspace search results. int maxWorkspaceSearchResults = 1000; @@ -63,26 +63,30 @@ struct Config { int clientVersion = 0; }; MAKE_REFLECT_STRUCT(Config, - cacheDirectory, + cacheDirectory, - extraClangArguments, + extraClangArguments, - indexWhitelist, indexBlacklist, - logSkippedPathsForIndex, + indexWhitelist, + indexBlacklist, + logSkippedPathsForIndex, - maxWorkspaceSearchResults, - indexerCount, - enableIndexing, enableCacheWrite, enableCacheRead, + maxWorkspaceSearchResults, + indexerCount, + enableIndexing, + enableCacheWrite, + enableCacheRead, - includeCompletionMaximumPathLength, - includeCompletionWhitelistLiteralEnding, - includeCompletionWhitelist, includeCompletionBlacklist, + includeCompletionMaximumPathLength, + includeCompletionWhitelistLiteralEnding, + includeCompletionWhitelist, + includeCompletionBlacklist, - showDocumentLinksOnIncludes, + showDocumentLinksOnIncludes, - diagnosticsOnParse, - diagnosticsOnCodeCompletion, + diagnosticsOnParse, + diagnosticsOnCodeCompletion, - codeLensOnLocalVariables, + codeLensOnLocalVariables, - clientVersion); \ No newline at end of file + clientVersion); \ No newline at end of file diff --git a/src/file_consumer.cc b/src/file_consumer.cc index a2c53d14..9c1d0aa3 100644 --- a/src/file_consumer.cc +++ b/src/file_consumer.cc @@ -6,7 +6,8 @@ #include "utils.h" bool operator==(const CXFileUniqueID& a, const CXFileUniqueID& b) { - return a.data[0] == b.data[0] && a.data[1] == b.data[1] && a.data[2] == b.data[2]; + return a.data[0] == b.data[0] && a.data[1] == b.data[1] && + a.data[2] == b.data[2]; } bool FileConsumer::SharedState::Mark(const std::string& file) { @@ -21,7 +22,8 @@ void FileConsumer::SharedState::Reset(const std::string& file) { files.erase(it); } -FileConsumer::FileConsumer(SharedState* shared_state, const std::string& parse_file) +FileConsumer::FileConsumer(SharedState* shared_state, + const std::string& parse_file) : shared_(shared_state), parse_file_(parse_file) {} IndexFile* FileConsumer::TryConsumeFile(CXFile file, bool* is_first_ownership) { @@ -86,7 +88,8 @@ void FileConsumer::EmitError(CXFile file) const { std::string file_name = clang::ToString(clang_getFileName(file)); // TODO: Investigate this more, why can we get an empty file name? if (!file_name.empty()) { - std::string error_message = "Could not get unique file id for " + file_name + " when parsing " + parse_file_; + std::string error_message = "Could not get unique file id for " + + file_name + " when parsing " + parse_file_; std::cerr << error_message << std::endl; } } \ No newline at end of file diff --git a/src/file_consumer.h b/src/file_consumer.h index 322e5e58..562823bc 100644 --- a/src/file_consumer.h +++ b/src/file_consumer.h @@ -6,8 +6,9 @@ #include #include -#include #include +#include + struct IndexFile; diff --git a/src/include_complete.cc b/src/include_complete.cc index e3362d43..6385524b 100644 --- a/src/include_complete.cc +++ b/src/include_complete.cc @@ -27,7 +27,8 @@ std::string ElideLongPath(Config* config, const std::string& path) { return ".." + path.substr(start + 2); } -size_t TrimCommonPathPrefix(const std::string& result, const std::string& trimmer) { +size_t TrimCommonPathPrefix(const std::string& result, + const std::string& trimmer) { size_t i = 0; while (i < result.size() && i < trimmer.size()) { char a = result[i]; @@ -47,7 +48,9 @@ size_t TrimCommonPathPrefix(const std::string& result, const std::string& trimme } // Returns true iff angle brackets should be used. -bool TrimPath(Project* project, const std::string& project_root, std::string* insert_path) { +bool TrimPath(Project* project, + const std::string& project_root, + std::string* insert_path) { size_t start = 0; bool angle = false; @@ -73,7 +76,10 @@ bool TrimPath(Project* project, const std::string& project_root, std::string* in return angle; } -lsCompletionItem BuildCompletionItem(Config* config, const std::string& path, bool use_angle_brackets, bool is_stl) { +lsCompletionItem BuildCompletionItem(Config* config, + const std::string& path, + bool use_angle_brackets, + bool is_stl) { lsCompletionItem item; if (use_angle_brackets) item.label = "#include <" + ElideLongPath(config, path) + ">"; @@ -111,15 +117,18 @@ void IncludeComplete::Rescan() { completion_items.clear(); absolute_path_to_completion_item.clear(); - if (!match_ && (!config_->includeCompletionWhitelist.empty() || !config_->includeCompletionBlacklist.empty())) - match_ = MakeUnique(config_->includeCompletionWhitelist, config_->includeCompletionBlacklist); + if (!match_ && (!config_->includeCompletionWhitelist.empty() || + !config_->includeCompletionBlacklist.empty())) + match_ = MakeUnique(config_->includeCompletionWhitelist, + config_->includeCompletionBlacklist); is_scanning = true; WorkThread::StartThread("include_scanner", [this]() { Timer timer; InsertStlIncludes(); - InsertIncludesFromDirectory(config_->projectRoot, false /*use_angle_brackets*/); + InsertIncludesFromDirectory(config_->projectRoot, + false /*use_angle_brackets*/); for (const std::string& dir : project_->quote_include_directories) InsertIncludesFromDirectory(dir, false /*use_angle_brackets*/); for (const std::string& dir : project_->angle_include_directories) @@ -133,48 +142,60 @@ void IncludeComplete::Rescan() { } void IncludeComplete::AddFile(const std::string& absolute_path) { - if (!EndsWithAny(absolute_path, config_->includeCompletionWhitelistLiteralEnding)) + if (!EndsWithAny(absolute_path, + config_->includeCompletionWhitelistLiteralEnding)) return; if (match_ && !match_->IsMatch(absolute_path)) return; std::string trimmed_path = absolute_path; - bool use_angle_brackets = TrimPath(project_, config_->projectRoot, &trimmed_path); - lsCompletionItem item = BuildCompletionItem(config_, trimmed_path, use_angle_brackets, false /*is_stl*/); + bool use_angle_brackets = + TrimPath(project_, config_->projectRoot, &trimmed_path); + lsCompletionItem item = BuildCompletionItem( + config_, trimmed_path, use_angle_brackets, false /*is_stl*/); if (is_scanning) { std::lock_guard lock(completion_items_mutex); - if (absolute_path_to_completion_item.insert(std::make_pair(absolute_path, completion_items.size())).second) + if (absolute_path_to_completion_item + .insert(std::make_pair(absolute_path, completion_items.size())) + .second) completion_items.push_back(item); - } - else { - if (absolute_path_to_completion_item.insert(std::make_pair(absolute_path, completion_items.size())).second) + } else { + if (absolute_path_to_completion_item + .insert(std::make_pair(absolute_path, completion_items.size())) + .second) completion_items.push_back(item); } } -void IncludeComplete::InsertIncludesFromDirectory( - std::string directory, - bool use_angle_brackets) { +void IncludeComplete::InsertIncludesFromDirectory(std::string directory, + bool use_angle_brackets) { directory = NormalizePath(directory); EnsureEndsInSlash(directory); std::vector results; - GetFilesInFolder(directory, true /*recursive*/, false /*add_folder_to_path*/, [&](const std::string& path) { - if (!EndsWithAny(path, config_->includeCompletionWhitelistLiteralEnding)) - return; - if (match_ && !match_->IsMatch(directory + path)) - return; + GetFilesInFolder( + directory, true /*recursive*/, false /*add_folder_to_path*/, + [&](const std::string& path) { + if (!EndsWithAny(path, + config_->includeCompletionWhitelistLiteralEnding)) + return; + if (match_ && !match_->IsMatch(directory + path)) + return; - CompletionCandidate candidate; - candidate.absolute_path = directory + path; - candidate.completion_item = BuildCompletionItem(config_, path, use_angle_brackets, false /*is_stl*/); - results.push_back(candidate); - }); + CompletionCandidate candidate; + candidate.absolute_path = directory + path; + candidate.completion_item = BuildCompletionItem( + config_, path, use_angle_brackets, false /*is_stl*/); + results.push_back(candidate); + }); std::lock_guard lock(completion_items_mutex); for (const CompletionCandidate& result : results) { - if (absolute_path_to_completion_item.insert(std::make_pair(result.absolute_path, completion_items.size())).second) + if (absolute_path_to_completion_item + .insert( + std::make_pair(result.absolute_path, completion_items.size())) + .second) completion_items.push_back(result.completion_item); } } @@ -182,11 +203,13 @@ void IncludeComplete::InsertIncludesFromDirectory( void IncludeComplete::InsertStlIncludes() { std::lock_guard lock(completion_items_mutex); for (const char* stl_header : kStandardLibraryIncludes) { - completion_items.push_back(BuildCompletionItem(config_, stl_header, true /*use_angle_brackets*/, true /*is_stl*/)); + completion_items.push_back(BuildCompletionItem( + config_, stl_header, true /*use_angle_brackets*/, true /*is_stl*/)); } } -optional IncludeComplete::FindCompletionItemForAbsolutePath(const std::string& absolute_path) { +optional IncludeComplete::FindCompletionItemForAbsolutePath( + const std::string& absolute_path) { std::lock_guard lock(completion_items_mutex); auto it = absolute_path_to_completion_item.find(absolute_path); diff --git a/src/include_complete.h b/src/include_complete.h index 0dcd335f..8ea081ed 100644 --- a/src/include_complete.h +++ b/src/include_complete.h @@ -18,18 +18,20 @@ struct IncludeComplete { // Ensures the one-off file is inside |completion_items|. void AddFile(const std::string& absolute_path); - // Scans the given directory and inserts all includes from this. This is a + // Scans the given directory and inserts all includes from this. This is a // blocking function and should be run off the querydb thread. - void InsertIncludesFromDirectory(std::string directory, bool use_angle_brackets); + void InsertIncludesFromDirectory(std::string directory, + bool use_angle_brackets); void InsertStlIncludes(); - optional FindCompletionItemForAbsolutePath(const std::string& absolute_path); + optional FindCompletionItemForAbsolutePath( + const std::string& absolute_path); // Guards |completion_items| when |is_scanning| is true. std::mutex completion_items_mutex; std::atomic is_scanning; std::vector completion_items; - + // Absolute file path to the completion item in |completion_items|. Also // verifies that we only have one completion item per absolute path. // We cannot just scan |completion_items| for this information because the @@ -42,4 +44,3 @@ struct IncludeComplete { Project* project_; std::unique_ptr match_; }; - diff --git a/src/indexer.cc b/src/indexer.cc index 74d14813..883e213a 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -14,7 +14,8 @@ #include #include -// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on |Foobar| in DISALLOW_COPY(Foobar) +// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on +// |Foobar| in DISALLOW_COPY(Foobar) namespace { @@ -31,13 +32,13 @@ Range Resolve(const CXSourceRange& range, CXFile* cx_file = nullptr) { CXSourceLocation end = clang_getRangeEnd(range); unsigned int start_line, start_column; - clang_getSpellingLocation(start, cx_file, &start_line, &start_column, nullptr); + clang_getSpellingLocation(start, cx_file, &start_line, &start_column, + nullptr); unsigned int end_line, end_column; clang_getSpellingLocation(end, nullptr, &end_line, &end_column, nullptr); - return Range( - Position((int16_t)start_line, (int16_t)start_column) /*start*/, - Position((int16_t)end_line, (int16_t)end_column) /*end*/); + return Range(Position((int16_t)start_line, (int16_t)start_column) /*start*/, + Position((int16_t)end_line, (int16_t)end_column) /*end*/); } Range ResolveSpelling(const CXCursor& cx_cursor, CXFile* cx_file = nullptr) { @@ -50,19 +51,18 @@ Range ResolveExtent(const CXCursor& cx_cursor, CXFile* cx_file = nullptr) { return Resolve(cx_range, cx_file); } - struct NamespaceHelper { std::unordered_map container_usr_to_qualified_name; void RegisterQualifiedName(std::string usr, - const CXIdxContainerInfo* container, - std::string qualified_name) { + const CXIdxContainerInfo* container, + std::string qualified_name) { if (container) { std::string container_usr = clang::Cursor(container->cursor).get_usr(); auto it = container_usr_to_qualified_name.find(container_usr); if (it != container_usr_to_qualified_name.end()) { container_usr_to_qualified_name[usr] = - it->second + qualified_name + "::"; + it->second + qualified_name + "::"; return; } } @@ -71,7 +71,7 @@ struct NamespaceHelper { } std::string QualifiedName(const CXIdxContainerInfo* container, - std::string unqualified_name) { + std::string unqualified_name) { if (container) { std::string container_usr = clang::Cursor(container->cursor).get_usr(); auto it = container_usr_to_qualified_name.find(container_usr); @@ -109,12 +109,14 @@ struct IndexParam { FileConsumer* file_consumer = nullptr; NamespaceHelper ns; - IndexParam(clang::TranslationUnit* tu, FileConsumer* file_consumer) : tu(tu), file_consumer(file_consumer) {} + IndexParam(clang::TranslationUnit* tu, FileConsumer* file_consumer) + : tu(tu), file_consumer(file_consumer) {} }; IndexFile* ConsumeFile(IndexParam* param, CXFile file) { bool is_first_ownership = false; - IndexFile* db = param->file_consumer->TryConsumeFile(file, &is_first_ownership); + IndexFile* db = + param->file_consumer->TryConsumeFile(file, &is_first_ownership); // If this is the first time we have seen the file (ignoring if we are // generating an index for it): @@ -129,18 +131,21 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) { // Set modification time. optional modification_time = GetLastModificationTime(file_name); - LOG_IF_S(ERROR, !modification_time) << "Failed fetching modification time for " << file_name; + LOG_IF_S(ERROR, !modification_time) + << "Failed fetching modification time for " << file_name; if (modification_time) param->file_modification_times[file_name] = *modification_time; // Capture file contents in |param->file_contents| if it was not specified // at the start of indexing. - if (db && param->file_contents.find(file_name) == param->file_contents.end()) { + if (db && + param->file_contents.find(file_name) == param->file_contents.end()) { optional content = ReadContent(file_name); if (content) param->file_contents[file_name] = *content; else - LOG_S(ERROR) << "[indexer] Failed to read file content for " << file_name; + LOG_S(ERROR) << "[indexer] Failed to read file content for " + << file_name; } } } @@ -179,18 +184,20 @@ bool IsLocalSemanticContainer(CXCursorKind kind) { // actually being written in the source code. bool CanBeCalledImplicitly(CXIdxEntityKind kind) { switch (kind) { - case CXIdxEntity_CXXConstructor: - case CXIdxEntity_CXXConversionFunction: - case CXIdxEntity_CXXDestructor: - return true; - default: - return false; + case CXIdxEntity_CXXConstructor: + case CXIdxEntity_CXXConversionFunction: + case CXIdxEntity_CXXDestructor: + return true; + default: + return false; } } // Returns true if the cursor spelling contains the given string. This is // useful to check for implicit function calls. -bool CursorSpellingContainsString(CXCursor cursor, CXTranslationUnit cx_tu, std::string scanning_for) { +bool CursorSpellingContainsString(CXCursor cursor, + CXTranslationUnit cx_tu, + std::string scanning_for) { CXSourceRange range = clang_Cursor_getSpellingNameRange(cursor, 0, 0); CXToken* tokens; unsigned num_tokens; @@ -213,7 +220,8 @@ bool CursorSpellingContainsString(CXCursor cursor, CXTranslationUnit cx_tu, std: // Returns the document content for the given range. May not work perfectly // when there are tabs instead of spaces. -std::string GetDocumentContentInRange(CXTranslationUnit cx_tu, CXSourceRange range) { +std::string GetDocumentContentInRange(CXTranslationUnit cx_tu, + CXSourceRange range) { std::string result; CXToken* tokens; @@ -227,7 +235,8 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu, CXSourceRange ran Range token_range = Resolve(clang_getTokenExtent(cx_tu, tokens[i])); if (previous_token_range) { // Insert newlines. - int16_t line_delta = token_range.start.line - previous_token_range->end.line; + int16_t line_delta = + token_range.start.line - previous_token_range->end.line; assert(line_delta >= 0); if (line_delta > 0) { result.append((size_t)line_delta, '\n'); @@ -235,7 +244,8 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu, CXSourceRange ran previous_token_range->end.column = 0; } // Insert spaces. - int16_t column_delta = token_range.start.column - previous_token_range->end.column; + int16_t column_delta = + token_range.start.column - previous_token_range->end.column; assert(column_delta >= 0); result.append((size_t)column_delta, ' '); } @@ -381,7 +391,7 @@ void UniqueAdd(std::vector& values, T value) { } IdCache::IdCache(const std::string& primary_file) - : primary_file(primary_file) {} + : primary_file(primary_file) {} template bool Contains(const std::vector& vec, const T& element) { @@ -640,7 +650,6 @@ optional AddDeclTypeUsages( clang::Cursor decl_cursor, const CXIdxContainerInfo* semantic_container, const CXIdxContainerInfo* lexical_container) { - // std::cerr << std::endl << "AddDeclUsages " << decl_cursor.get_spelling() << // std::endl; // Dump(decl_cursor); @@ -838,20 +847,20 @@ bool AreEqualLocations(CXIdxLoc loc, CXCursor cursor) { // clang_Cursor_getSpellingNameRange return clang_equalLocations( - clang_indexLoc_getCXSourceLocation(loc), - //clang_getRangeStart(clang_getCursorExtent(cursor))); - clang_getRangeStart(clang_Cursor_getSpellingNameRange(cursor, 0, 0))); + clang_indexLoc_getCXSourceLocation(loc), + // clang_getRangeStart(clang_getCursorExtent(cursor))); + clang_getRangeStart(clang_Cursor_getSpellingNameRange(cursor, 0, 0))); } - - - -clang::VisiterResult VisitMacroDefinitionAndExpansions(clang::Cursor cursor, clang::Cursor parent, IndexParam* param) { +clang::VisiterResult VisitMacroDefinitionAndExpansions(clang::Cursor cursor, + clang::Cursor parent, + IndexParam* param) { switch (cursor.get_kind()) { case CXCursor_MacroDefinition: case CXCursor_MacroExpansion: { // Resolve location, find IndexFile instance. - CXSourceRange cx_source_range = clang_Cursor_getSpellingNameRange(cursor.cx_cursor, 0, 0); + CXSourceRange cx_source_range = + clang_Cursor_getSpellingNameRange(cursor.cx_cursor, 0, 0); CXSourceLocation start = clang_getRangeStart(cx_source_range); if (clang_Location_isInSystemHeader(start)) break; @@ -881,7 +890,8 @@ clang::VisiterResult VisitMacroDefinitionAndExpansions(clang::Cursor cursor, cla var_def->def.is_local = false; var_def->def.is_macro = true; var_def->def.definition_spelling = decl_loc_spelling; - var_def->def.definition_extent = ResolveExtent(cursor.cx_cursor);; + var_def->def.definition_extent = ResolveExtent(cursor.cx_cursor); + ; } break; @@ -945,13 +955,16 @@ clang::VisiterResult VisitMacroDefinitionAndExpansions(clang::Cursor cursor, cla void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { - if (!kIndexStdDeclarations && clang_Location_isInSystemHeader(clang_indexLoc_getCXSourceLocation(decl->loc))) + if (!kIndexStdDeclarations && + clang_Location_isInSystemHeader( + clang_indexLoc_getCXSourceLocation(decl->loc))) return; assert(AreEqualLocations(decl->loc, decl->cursor)); CXFile file; - clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(decl->loc), &file, nullptr, nullptr, nullptr); + clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(decl->loc), + &file, nullptr, nullptr, nullptr); IndexParam* param = static_cast(client_data); IndexFile* db = ConsumeFile(param, file); if (!db) @@ -959,8 +972,9 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { NamespaceHelper* ns = ¶m->ns; - - //std::cerr << "DECL kind=" << decl->entityInfo->kind << " at " << db->id_cache.Resolve(decl->cursor, false).ToPrettyString(&db->id_cache) << std::endl; + // std::cerr << "DECL kind=" << decl->entityInfo->kind << " at " << + // db->id_cache.Resolve(decl->cursor, false).ToPrettyString(&db->id_cache) << + // std::endl; switch (decl->entityInfo->kind) { case CXIdxEntity_CXXNamespace: { @@ -993,18 +1007,23 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // if (!decl->isRedeclaration) { var->def.short_name = decl->entityInfo->name; - std::string type_name = clang::ToString(clang_getTypeSpelling(clang_getCursorType(decl->cursor))); - var->def.detailed_name = type_name + " " + ns->QualifiedName(decl->semanticContainer, var->def.short_name); + std::string type_name = clang::ToString( + clang_getTypeSpelling(clang_getCursorType(decl->cursor))); + var->def.detailed_name = + type_name + " " + + ns->QualifiedName(decl->semanticContainer, var->def.short_name); - var->def.is_local = !decl->semanticContainer || IsLocalSemanticContainer(decl->semanticContainer->cursor.kind); + var->def.is_local = + !decl->semanticContainer || + IsLocalSemanticContainer(decl->semanticContainer->cursor.kind); //} if (decl->isDefinition) { var->def.definition_spelling = ResolveSpelling(decl->cursor); - var->def.definition_extent = ResolveExtent(decl->cursor);; - } - else { + var->def.definition_extent = ResolveExtent(decl->cursor); + ; + } else { var->def.declaration = ResolveSpelling(decl->cursor); } UniqueAdd(var->uses, decl_loc_spelling); @@ -1020,17 +1039,19 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // the function declaration is encountered since we won't receive ParmDecl // declarations for unnamed parameters. // TODO: See if we can remove this function call. - AddDeclTypeUsages( - db, decl_cursor, - decl->semanticContainer, decl->lexicalContainer); + AddDeclTypeUsages(db, decl_cursor, decl->semanticContainer, + decl->lexicalContainer); // We don't need to assign declaring type multiple times if this variable // has already been seen. if (!decl->isRedeclaration) { - optional var_type = ResolveToDeclarationType(db, decl_cursor); + optional var_type = + ResolveToDeclarationType(db, decl_cursor); if (var_type.has_value()) { // Don't treat enum definition variables as instantiations. - bool is_enum_member = decl->semanticContainer && decl->semanticContainer->cursor.kind == CXCursor_EnumDecl; + bool is_enum_member = + decl->semanticContainer && + decl->semanticContainer->cursor.kind == CXCursor_EnumDecl; if (!is_enum_member) db->Resolve(var_type.value())->instances.push_back(var_id); @@ -1038,10 +1059,11 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { } } - // TODO: Refactor handlers so more things are under 'if (!decl->isRedeclaration)' + // TODO: Refactor handlers so more things are under 'if + // (!decl->isRedeclaration)' if (decl->isDefinition && IsTypeDefinition(decl->semanticContainer)) { IndexTypeId declaring_type_id = - db->ToTypeId(decl->semanticContainer->cursor); + db->ToTypeId(decl->semanticContainer->cursor); IndexType* declaring_type_def = db->Resolve(declaring_type_id); var->def.declaring_type = declaring_type_id; declaring_type_def->def.vars.push_back(var_id); @@ -1060,7 +1082,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { Range decl_extent = ResolveExtent(decl->cursor); clang::Cursor decl_cursor = decl->cursor; - clang::Cursor decl_cursor_resolved = decl_cursor.template_specialization_to_template_definition(); + clang::Cursor decl_cursor_resolved = + decl_cursor.template_specialization_to_template_definition(); bool is_template_specialization = decl_cursor != decl_cursor_resolved; IndexFuncId func_id = db->ToFuncId(decl_cursor_resolved.cx_cursor); @@ -1068,8 +1091,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // We don't actually need to know the return type, but we need to mark it // as an interesting usage. - AddDeclTypeUsages(db, decl_cursor, - decl->semanticContainer, decl->lexicalContainer); + AddDeclTypeUsages(db, decl_cursor, decl->semanticContainer, + decl->lexicalContainer); // Add definition or declaration. This is a bit tricky because we treat // template specializations as declarations, even though they are @@ -1077,16 +1100,16 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // TODO: Support multiple function definitions, which is common for // template specializations. if (decl->isDefinition && !is_template_specialization) { - //assert(!func->def.definition_spelling); - //assert(!func->def.definition_extent); + // assert(!func->def.definition_spelling); + // assert(!func->def.definition_extent); func->def.definition_spelling = decl_spelling; func->def.definition_extent = decl_extent; - } - else { + } else { IndexFunc::Declaration declaration; declaration.spelling = decl_spelling; declaration.extent = decl_extent; - declaration.content = GetDocumentContentInRange(param->tu->cx_tu, clang_getCursorExtent(decl->cursor)); + declaration.content = GetDocumentContentInRange( + param->tu->cx_tu, clang_getCursorExtent(decl->cursor)); // Add parameters. for (clang::Cursor arg : decl_cursor.get_arguments()) { @@ -1096,7 +1119,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // If the name is empty (which is common for parameters), clang // will report a range with length 1, which is not correct. - if (param_spelling.start.column == (param_spelling.end.column - 1) && + if (param_spelling.start.column == + (param_spelling.end.column - 1) && arg.get_display_name().empty()) { param_spelling.end.column -= 1; } @@ -1122,7 +1146,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // Build detailed name. The type desc looks like void (void *). We // insert the qualified name before the first '('. - std::string qualified_name = ns->QualifiedName(decl->semanticContainer, func->def.short_name); + std::string qualified_name = + ns->QualifiedName(decl->semanticContainer, func->def.short_name); std::string type_desc = decl_cursor.get_type_description(); size_t offset = type_desc.find('('); type_desc.insert(offset, qualified_name); @@ -1142,7 +1167,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { UniqueAdd(declaring_type_def->uses, decl_spelling); if (decl->entityInfo->kind == CXIdxEntity_CXXDestructor) { Range dtor_type_range = decl_spelling; - dtor_type_range.start.column += 1; // Don't count the leading ~ + dtor_type_range.start.column += 1; // Don't count the leading ~ UniqueAdd(declaring_type_def->uses, dtor_type_range); } @@ -1155,12 +1180,13 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { CXCursor* overridden; unsigned int num_overridden; clang_getOverriddenCursors(decl->cursor, &overridden, - &num_overridden); + &num_overridden); // FIXME if it ever shows up. Methods should only ever have 1 base // type, though. if (num_overridden > 1) - std::cerr << "[indexer]: warning: multiple base overrides for " << func->def.detailed_name << std::endl; + std::cerr << "[indexer]: warning: multiple base overrides for " + << func->def.detailed_name << std::endl; for (unsigned i = 0; i < num_overridden; ++i) { clang::Cursor parent = overridden[i]; @@ -1185,9 +1211,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // Note we want to fetch the first TypeRef. Running // ResolveCursorType(decl->cursor) would return // the type of the typedef/using, not the type of the referenced type. - optional alias_of = - AddDeclTypeUsages(db, decl->cursor, - decl->semanticContainer, decl->lexicalContainer); + optional alias_of = AddDeclTypeUsages( + db, decl->cursor, decl->semanticContainer, decl->lexicalContainer); IndexTypeId type_id = db->ToTypeId(decl->entityInfo->USR); IndexType* type = db->Resolve(type_id); @@ -1254,15 +1279,14 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { for (unsigned int i = 0; i < class_info->numBases; ++i) { const CXIdxBaseClassInfo* base_class = class_info->bases[i]; - AddDeclTypeUsages(db, base_class->cursor, - decl->semanticContainer, decl->lexicalContainer); + AddDeclTypeUsages(db, base_class->cursor, decl->semanticContainer, + decl->lexicalContainer); optional parent_type_id = ResolveToDeclarationType(db, base_class->cursor); // type_def ptr could be invalidated by ResolveToDeclarationType. type = db->Resolve(type_id); if (parent_type_id) { - IndexType* parent_type_def = - db->Resolve(parent_type_id.value()); + IndexType* parent_type_def = db->Resolve(parent_type_id.value()); parent_type_def->derived.push_back(type_id); type->def.parents.push_back(parent_type_id.value()); } @@ -1272,11 +1296,9 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { } default: - std::cerr - << "!! Unhandled indexDeclaration: " - << clang::Cursor(decl->cursor).ToString() << " at " - << ResolveSpelling(decl->cursor).start.ToString() - << std::endl; + std::cerr << "!! Unhandled indexDeclaration: " + << clang::Cursor(decl->cursor).ToString() << " at " + << ResolveSpelling(decl->cursor).start.ToString() << std::endl; std::cerr << " entityInfo->kind = " << decl->entityInfo->kind << std::endl; std::cerr << " entityInfo->USR = " << decl->entityInfo->USR @@ -1367,20 +1389,24 @@ bool IsFunctionCallContext(CXCursorKind kind) { void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { // Don't index references from or to system headers. - if (clang_Location_isInSystemHeader(clang_indexLoc_getCXSourceLocation(ref->loc)) || - clang_Location_isInSystemHeader(clang_getCursorLocation(ref->referencedEntity->cursor))) + if (clang_Location_isInSystemHeader( + clang_indexLoc_getCXSourceLocation(ref->loc)) || + clang_Location_isInSystemHeader( + clang_getCursorLocation(ref->referencedEntity->cursor))) return; - //assert(AreEqualLocations(ref->loc, ref->cursor)); + // assert(AreEqualLocations(ref->loc, ref->cursor)); -// if (clang_Location_isInSystemHeader(clang_getCursorLocation(ref->cursor)) || -// clang_Location_isInSystemHeader( -// clang_getCursorLocation(ref->referencedEntity->cursor))) -// return; + // if (clang_Location_isInSystemHeader(clang_getCursorLocation(ref->cursor)) + // || + // clang_Location_isInSystemHeader( + // clang_getCursorLocation(ref->referencedEntity->cursor))) + // return; // TODO: Use clang_getFileUniqueID CXFile file; - clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(ref->loc), &file, nullptr, nullptr, nullptr); + clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(ref->loc), &file, + nullptr, nullptr, nullptr); IndexParam* param = static_cast(client_data); IndexFile* db = ConsumeFile(param, file); if (!db) @@ -1390,17 +1416,18 @@ void indexEntityReference(CXClientData client_data, // ref->loc mainFile=1 // ref->referencedEntity mainFile=1 // - // Regardless, we need to do more advanced location processing to handle multiple output IndexFile instances. - //bool mainFile = clang_Location_isFromMainFile(clang_indexLoc_getCXSourceLocation(ref->loc)); - //Range loc_spelling = param->db->id_cache.ForceResolveSpelling(ref->cursor, false /*interesting*/); - //std::cerr << "mainFile: " << mainFile << ", loc: " << loc_spelling.ToString() << std::endl; + // Regardless, we need to do more advanced location processing to handle + // multiple output IndexFile instances. + // bool mainFile = + // clang_Location_isFromMainFile(clang_indexLoc_getCXSourceLocation(ref->loc)); + // Range loc_spelling = param->db->id_cache.ForceResolveSpelling(ref->cursor, + // false /*interesting*/); std::cerr << "mainFile: " << mainFile << ", loc: " + // << loc_spelling.ToString() << std::endl; // Don't index references that are not from the main file. - //if (!clang_Location_isFromMainFile(clang_getCursorLocation(ref->cursor))) + // if (!clang_Location_isFromMainFile(clang_getCursorLocation(ref->cursor))) // return; - - clang::Cursor cursor(ref->cursor); // std::cerr << "REF kind=" << ref->referencedEntity->kind << " at " << @@ -1453,8 +1480,10 @@ void indexEntityReference(CXClientData client_data, // libclang doesn't provide a nice api to check if the given function // call is implicit. ref->kind should probably work (it's either direct // or implicit), but libclang only supports implicit for objective-c. - bool is_implicit = CanBeCalledImplicitly(ref->referencedEntity->kind) && - !CursorSpellingContainsString(ref->cursor, param->tu->cx_tu, called->def.short_name); + bool is_implicit = + CanBeCalledImplicitly(ref->referencedEntity->kind) && + !CursorSpellingContainsString(ref->cursor, param->tu->cx_tu, + called->def.short_name); if (IsFunctionCallContext(ref->container->cursor.kind)) { IndexFuncId caller_id = db->ToFuncId(ref->container->cursor); @@ -1462,8 +1491,10 @@ void indexEntityReference(CXClientData client_data, // Calling db->ToFuncId invalidates the FuncDef* ptrs. called = db->Resolve(called_id); - AddFuncRef(&caller->def.callees, IndexFuncRef(called_id, loc_spelling, is_implicit)); - AddFuncRef(&called->callers, IndexFuncRef(caller_id, loc_spelling, is_implicit)); + AddFuncRef(&caller->def.callees, + IndexFuncRef(called_id, loc_spelling, is_implicit)); + AddFuncRef(&called->callers, + IndexFuncRef(caller_id, loc_spelling, is_implicit)); } else { AddFuncRef(&called->callers, IndexFuncRef(loc_spelling, is_implicit)); } @@ -1478,7 +1509,8 @@ void indexEntityReference(CXClientData client_data, case CXIdxEntity_Struct: case CXIdxEntity_CXXClass: { clang::Cursor referenced_cursor = ref->referencedEntity->cursor; - referenced_cursor = referenced_cursor.template_specialization_to_template_definition(); + referenced_cursor = + referenced_cursor.template_specialization_to_template_definition(); IndexTypeId referenced_id = db->ToTypeId(referenced_cursor.get_usr()); IndexType* referenced = db->Resolve(referenced_id); @@ -1503,20 +1535,16 @@ void indexEntityReference(CXClientData client_data, } default: - std::cerr - << "!! Unhandled indexEntityReference: " << cursor.ToString() - << " at " - << ResolveSpelling(ref->cursor).start.ToString() - << std::endl; + std::cerr << "!! Unhandled indexEntityReference: " << cursor.ToString() + << " at " << ResolveSpelling(ref->cursor).start.ToString() + << std::endl; std::cerr << " ref->referencedEntity->kind = " << ref->referencedEntity->kind << std::endl; if (ref->parentEntity) std::cerr << " ref->parentEntity->kind = " << ref->parentEntity->kind << std::endl; - std::cerr - << " ref->loc = " - << ResolveSpelling(ref->cursor).start.ToString() - << std::endl; + std::cerr << " ref->loc = " + << ResolveSpelling(ref->cursor).start.ToString() << std::endl; std::cerr << " ref->kind = " << ref->kind << std::endl; if (ref->parentEntity) std::cerr << " parentEntity = " @@ -1563,17 +1591,18 @@ void indexEntityReference(CXClientData client_data, -FileContents::FileContents(const std::string& path, const std::string& content) : path(path), content(content) {} +FileContents::FileContents(const std::string& path, const std::string& content) + : path(path), content(content) {} std::vector> Parse( - Config* config, FileConsumer::SharedState* file_consumer_shared, + Config* config, + FileConsumer::SharedState* file_consumer_shared, std::string file, std::vector args, std::vector file_contents, PerformanceImportFile* perf, clang::Index* index, bool dump_ast) { - if (!config->enableIndexing) return {}; @@ -1590,9 +1619,12 @@ std::vector> Parse( unsaved_files.push_back(unsaved); } - clang::TranslationUnit tu(index, file, args, unsaved_files, CXTranslationUnit_KeepGoing | CXTranslationUnit_DetailedPreprocessingRecord); + clang::TranslationUnit tu(index, file, args, unsaved_files, + CXTranslationUnit_KeepGoing | + CXTranslationUnit_DetailedPreprocessingRecord); if (tu.did_fail) { - std::cerr << "!! Failed creating translation unit for " << file << std::endl; + std::cerr << "!! Failed creating translation unit for " << file + << std::endl; return {}; } @@ -1601,12 +1633,10 @@ std::vector> Parse( if (dump_ast) Dump(tu.document_cursor()); - - IndexerCallbacks callbacks[] = { - {&abortQuery, &diagnostic, &enteredMainFile, &ppIncludedFile, - &importedASTFile, &startedTranslationUnit, &indexDeclaration, - &indexEntityReference} - }; + IndexerCallbacks callbacks[] = {{&abortQuery, &diagnostic, &enteredMainFile, + &ppIncludedFile, &importedASTFile, + &startedTranslationUnit, &indexDeclaration, + &indexEntityReference}}; FileConsumer file_consumer(file_consumer_shared, file); IndexParam param(&tu, &file_consumer); @@ -1617,16 +1647,19 @@ std::vector> Parse( CXFile cx_file = clang_getFile(tu.cx_tu, file.c_str()); param.primary_file = ConsumeFile(¶m, cx_file); - //std::cerr << "!! [START] Indexing " << file << std::endl; + // std::cerr << "!! [START] Indexing " << file << std::endl; CXIndexAction index_action = clang_IndexAction_create(index->cx_index); clang_indexTranslationUnit(index_action, ¶m, callbacks, sizeof(callbacks), - CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession | CXIndexOpt_IndexImplicitTemplateInstantiations, + CXIndexOpt_IndexFunctionLocalSymbols | + CXIndexOpt_SkipParsedBodiesInSession | + CXIndexOpt_IndexImplicitTemplateInstantiations, tu.cx_tu); clang_IndexAction_dispose(index_action); - //std::cerr << "!! [END] Indexing " << file << std::endl; + // std::cerr << "!! [END] Indexing " << file << std::endl; - tu.document_cursor().VisitChildren(&VisitMacroDefinitionAndExpansions, ¶m); + tu.document_cursor().VisitChildren(&VisitMacroDefinitionAndExpansions, + ¶m); perf->index_build = timer.ElapsedMicrosecondsAndReset(); @@ -1655,7 +1688,6 @@ std::vector> Parse( return result; } - void IndexInit() { clang_enableStackTraces(); clang_toggleCrashRecovery(1); diff --git a/src/indexer.h b/src/indexer.h index 9949f98c..61127c48 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -1,28 +1,31 @@ #pragma once #include "file_consumer.h" -#include "position.h" -#include "serializer.h" -#include "utils.h" #include "language_server_api.h" #include "libclangmm/Index.h" #include "libclangmm/Utility.h" #include "performance.h" +#include "position.h" +#include "serializer.h" +#include "utils.h" + #include -#include +#include #include #include -#include +#include + #include -#include #include +#include #include #include #include #include + struct IndexType; struct IndexFunc; struct IndexVar; @@ -49,7 +52,7 @@ template struct hash> { size_t operator()(const Id& k) const { return hash()(k.id); } }; -} +} // namespace std template bool operator==(const Id& a, const Id& b) { @@ -61,11 +64,11 @@ bool operator!=(const Id& a, const Id& b) { return !(a == b); } -template +template void Reflect(Reader& visitor, Id& id) { id.id = visitor.GetUint64(); } -template +template void Reflect(Writer& visitor, Id& value) { visitor.Uint64(value.id); } @@ -76,7 +79,6 @@ using IndexVarId = Id; struct IdCache; - struct IndexFuncRef { // NOTE: id can be -1 if the function call is not coming from a function. IndexFuncId id; @@ -85,19 +87,25 @@ struct IndexFuncRef { IndexFuncRef() {} // For serialization. - IndexFuncRef(IndexFuncId id, Range loc, bool is_implicit) : id(id), loc(loc), is_implicit(is_implicit) {} - IndexFuncRef(Range loc, bool is_implicit) : id(IndexFuncId((size_t)-1)), loc(loc), is_implicit(is_implicit) {} + IndexFuncRef(IndexFuncId id, Range loc, bool is_implicit) + : id(id), loc(loc), is_implicit(is_implicit) {} + IndexFuncRef(Range loc, bool is_implicit) + : id(IndexFuncId((size_t)-1)), loc(loc), is_implicit(is_implicit) {} inline bool operator==(const IndexFuncRef& other) { - return id == other.id && loc == other.loc && is_implicit == other.is_implicit; + return id == other.id && loc == other.loc && + is_implicit == other.is_implicit; + } + inline bool operator!=(const IndexFuncRef& other) { + return !(*this == other); } - inline bool operator!=(const IndexFuncRef& other) { return !(*this == other); } inline bool operator<(const IndexFuncRef& other) const { if (id < other.id) return true; if (id == other.id && loc < other.loc) return true; - return id == other.id && loc == other.loc && is_implicit < other.is_implicit; + return id == other.id && loc == other.loc && + is_implicit < other.is_implicit; } }; @@ -125,10 +133,9 @@ inline void Reflect(Writer& visitor, IndexFuncRef& value) { if (value.is_implicit) s += "~"; - if (value.id.id == -1) { // id.id is unsigned, special case 0 value + if (value.id.id == -1) { // id.id is unsigned, special case 0 value s += "-1"; - } - else { + } else { s += std::to_string(value.id.id); } @@ -136,10 +143,7 @@ inline void Reflect(Writer& visitor, IndexFuncRef& value) { visitor.String(s.c_str()); } -template +template struct TypeDefDefinitionData { // General metadata. std::string usr; @@ -173,19 +177,18 @@ struct TypeDefDefinitionData { TypeDefDefinitionData() {} // For reflection. TypeDefDefinitionData(const std::string& usr) : usr(usr) {} - bool operator==(const TypeDefDefinitionData& - other) const { + bool operator==( + const TypeDefDefinitionData& other) const { return usr == other.usr && short_name == other.short_name && detailed_name == other.detailed_name && definition_spelling == other.definition_spelling && definition_extent == other.definition_extent && - alias_of == other.alias_of && - parents == other.parents && types == other.types && - funcs == other.funcs && vars == other.vars; + alias_of == other.alias_of && parents == other.parents && + types == other.types && funcs == other.funcs && vars == other.vars; } - bool operator!=(const TypeDefDefinitionData& - other) const { + bool operator!=( + const TypeDefDefinitionData& other) const { return !(*this == other); } }; @@ -211,7 +214,8 @@ void Reflect(TVisitor& visitor, } struct IndexType { - using Def = TypeDefDefinitionData; + using Def = + TypeDefDefinitionData; Def def; IndexTypeId id; @@ -268,8 +272,8 @@ struct FuncDefDefinitionData { } bool operator==( - const FuncDefDefinitionData& - other) const { + const FuncDefDefinitionData& other) + const { return usr == other.usr && short_name == other.short_name && detailed_name == other.detailed_name && definition_spelling == other.definition_spelling && @@ -278,8 +282,8 @@ struct FuncDefDefinitionData { locals == other.locals && callees == other.callees; } bool operator!=( - const FuncDefDefinitionData& - other) const { + const FuncDefDefinitionData& other) + const { return !(*this == other); } }; @@ -307,7 +311,11 @@ void Reflect( } struct IndexFunc { - using Def = FuncDefDefinitionData; + using Def = FuncDefDefinitionData; Def def; IndexFuncId id; @@ -346,12 +354,13 @@ struct IndexFunc { } }; MAKE_HASHABLE(IndexFunc, t.def.usr); -MAKE_REFLECT_STRUCT(IndexFunc::Declaration, spelling, extent, content, param_spellings); +MAKE_REFLECT_STRUCT(IndexFunc::Declaration, + spelling, + extent, + content, + param_spellings); -template +template struct VarDefDefinitionData { // General metadata. std::string usr; @@ -377,8 +386,8 @@ struct VarDefDefinitionData { VarDefDefinitionData() {} // For reflection. VarDefDefinitionData(const std::string& usr) : usr(usr) {} - bool operator==(const VarDefDefinitionData& - other) const { + bool operator==( + const VarDefDefinitionData& other) const { return usr == other.usr && short_name == other.short_name && detailed_name == other.detailed_name && declaration == other.declaration && @@ -387,8 +396,8 @@ struct VarDefDefinitionData { variable_type == other.variable_type && declaring_type == other.declaring_type; } - bool operator!=(const VarDefDefinitionData& - other) const { + bool operator!=( + const VarDefDefinitionData& other) const { return !(*this == other); } }; @@ -509,9 +518,11 @@ struct FileContents { // |import_file| is the cc file which is what gets passed to clang. // |desired_index_file| is the (h or cc) file which has actually changed. -// |dependencies| are the existing dependencies of |import_file| if this is a reparse. +// |dependencies| are the existing dependencies of |import_file| if this is a +// reparse. std::vector> Parse( - Config* config, FileConsumer::SharedState* file_consumer_shared, + Config* config, + FileConsumer::SharedState* file_consumer_shared, std::string file, std::vector args, std::vector file_contents, diff --git a/src/ipc.cc b/src/ipc.cc index 60db889a..aadea956 100644 --- a/src/ipc.cc +++ b/src/ipc.cc @@ -4,88 +4,87 @@ const char* IpcIdToString(IpcId id) { switch (id) { - case IpcId::CancelRequest: - return "$/cancelRequest"; - case IpcId::Initialize: - return "initialize"; - case IpcId::Initialized: - return "initialized"; - case IpcId::Exit: - return "exit"; - case IpcId::TextDocumentDidOpen: - return "textDocument/didOpen"; - case IpcId::TextDocumentDidChange: - return "textDocument/didChange"; - case IpcId::TextDocumentDidClose: - return "textDocument/didClose"; - case IpcId::TextDocumentDidSave: - return "textDocument/didSave"; - case IpcId::TextDocumentPublishDiagnostics: - return "textDocument/publishDiagnostics"; - case IpcId::TextDocumentRename: - return "textDocument/rename"; - case IpcId::TextDocumentCompletion: - return "textDocument/completion"; - case IpcId::TextDocumentSignatureHelp: - return "textDocument/signatureHelp"; - case IpcId::TextDocumentDefinition: - return "textDocument/definition"; - case IpcId::TextDocumentDocumentHighlight: - return "textDocument/documentHighlight"; - case IpcId::TextDocumentHover: - return "textDocument/hover"; - case IpcId::TextDocumentReferences: - return "textDocument/references"; - case IpcId::TextDocumentDocumentSymbol: - return "textDocument/documentSymbol"; - case IpcId::TextDocumentDocumentLink: - return "textDocument/documentLink"; - case IpcId::TextDocumentCodeAction: - return "textDocument/codeAction"; - case IpcId::TextDocumentCodeLens: - return "textDocument/codeLens"; - case IpcId::CodeLensResolve: - return "codeLens/resolve"; - case IpcId::WorkspaceSymbol: - return "workspace/symbol"; + case IpcId::CancelRequest: + return "$/cancelRequest"; + case IpcId::Initialize: + return "initialize"; + case IpcId::Initialized: + return "initialized"; + case IpcId::Exit: + return "exit"; + case IpcId::TextDocumentDidOpen: + return "textDocument/didOpen"; + case IpcId::TextDocumentDidChange: + return "textDocument/didChange"; + case IpcId::TextDocumentDidClose: + return "textDocument/didClose"; + case IpcId::TextDocumentDidSave: + return "textDocument/didSave"; + case IpcId::TextDocumentPublishDiagnostics: + return "textDocument/publishDiagnostics"; + case IpcId::TextDocumentRename: + return "textDocument/rename"; + case IpcId::TextDocumentCompletion: + return "textDocument/completion"; + case IpcId::TextDocumentSignatureHelp: + return "textDocument/signatureHelp"; + case IpcId::TextDocumentDefinition: + return "textDocument/definition"; + case IpcId::TextDocumentDocumentHighlight: + return "textDocument/documentHighlight"; + case IpcId::TextDocumentHover: + return "textDocument/hover"; + case IpcId::TextDocumentReferences: + return "textDocument/references"; + case IpcId::TextDocumentDocumentSymbol: + return "textDocument/documentSymbol"; + case IpcId::TextDocumentDocumentLink: + return "textDocument/documentLink"; + case IpcId::TextDocumentCodeAction: + return "textDocument/codeAction"; + case IpcId::TextDocumentCodeLens: + return "textDocument/codeLens"; + case IpcId::CodeLensResolve: + return "codeLens/resolve"; + case IpcId::WorkspaceSymbol: + return "workspace/symbol"; - case IpcId::CqueryPublishInactiveRegions: - return "$cquery/publishInactiveRegions"; + case IpcId::CqueryPublishInactiveRegions: + return "$cquery/publishInactiveRegions"; - case IpcId::CqueryFreshenIndex: - return "$cquery/freshenIndex"; - case IpcId::CqueryTypeHierarchyTree: - return "$cquery/typeHierarchyTree"; - case IpcId::CqueryCallTreeInitial: - return "$cquery/callTreeInitial"; - case IpcId::CqueryCallTreeExpand: - return "$cquery/callTreeExpand"; - case IpcId::CqueryVars: - return "$cquery/vars"; - case IpcId::CqueryCallers: - return "$cquery/callers"; - case IpcId::CqueryBase: - return "$cquery/base"; - case IpcId::CqueryDerived: - return "$cquery/derived"; + case IpcId::CqueryFreshenIndex: + return "$cquery/freshenIndex"; + case IpcId::CqueryTypeHierarchyTree: + return "$cquery/typeHierarchyTree"; + case IpcId::CqueryCallTreeInitial: + return "$cquery/callTreeInitial"; + case IpcId::CqueryCallTreeExpand: + return "$cquery/callTreeExpand"; + case IpcId::CqueryVars: + return "$cquery/vars"; + case IpcId::CqueryCallers: + return "$cquery/callers"; + case IpcId::CqueryBase: + return "$cquery/base"; + case IpcId::CqueryDerived: + return "$cquery/derived"; - case IpcId::Cout: - return "$cout"; + case IpcId::Cout: + return "$cout"; - case IpcId::CqueryIndexFile: - return "$cquery/indexFile"; - case IpcId::CqueryQueryDbWaitForIdleIndexer: - return "$cquery/queryDbWaitForIdleIndexer"; - case IpcId::CqueryExitWhenIdle: - return "$cquery/exitWhenIdle"; + case IpcId::CqueryIndexFile: + return "$cquery/indexFile"; + case IpcId::CqueryQueryDbWaitForIdleIndexer: + return "$cquery/queryDbWaitForIdleIndexer"; + case IpcId::CqueryExitWhenIdle: + return "$cquery/exitWhenIdle"; - default: - assert(false && "missing IpcId string name"); - exit(1); + default: + assert(false && "missing IpcId string name"); + exit(1); } } -BaseIpcMessage::BaseIpcMessage(IpcId method_id) - : method_id(method_id) {} +BaseIpcMessage::BaseIpcMessage(IpcId method_id) : method_id(method_id) {} BaseIpcMessage::~BaseIpcMessage() = default; \ No newline at end of file diff --git a/src/ipc.h b/src/ipc.h index a0811fd3..9c07121b 100644 --- a/src/ipc.h +++ b/src/ipc.h @@ -1,7 +1,8 @@ #pragma once -#include "utils.h" #include "serializer.h" +#include "utils.h" + #include @@ -40,10 +41,10 @@ enum class IpcId : int { CqueryCallTreeInitial, CqueryCallTreeExpand, // These are like DocumentReferences but show different types of data. - CqueryVars, // Show all variables of a type. - CqueryCallers, // Show all callers of a function. - CqueryBase, // Show base types/method. - CqueryDerived, // Show all derived types/methods. + CqueryVars, // Show all variables of a type. + CqueryCallers, // Show all callers of a function. + CqueryBase, // Show base types/method. + CqueryDerived, // Show all derived types/methods. // Internal implementation detail. Cout, @@ -88,10 +89,15 @@ struct Ipc_CqueryIndexFile : public IpcMessage { }; Params params; }; -MAKE_REFLECT_STRUCT(Ipc_CqueryIndexFile::Params, path, args, is_interactive, contents); +MAKE_REFLECT_STRUCT(Ipc_CqueryIndexFile::Params, + path, + args, + is_interactive, + contents); MAKE_REFLECT_STRUCT(Ipc_CqueryIndexFile, params); -struct Ipc_CqueryQueryDbWaitForIdleIndexer : public IpcMessage { +struct Ipc_CqueryQueryDbWaitForIdleIndexer + : public IpcMessage { static constexpr IpcId kIpcId = IpcId::CqueryQueryDbWaitForIdleIndexer; }; MAKE_REFLECT_EMPTY_STRUCT(Ipc_CqueryQueryDbWaitForIdleIndexer); diff --git a/src/ipc_manager.cc b/src/ipc_manager.cc index 5a872af7..af43e1bb 100644 --- a/src/ipc_manager.cc +++ b/src/ipc_manager.cc @@ -2,7 +2,7 @@ IpcManager* IpcManager::instance_ = nullptr; -// static +// static IpcManager* IpcManager::instance() { return instance_; } @@ -12,8 +12,10 @@ void IpcManager::CreateInstance(MultiQueueWaiter* waiter) { instance_ = new IpcManager(waiter); } -ThreadedQueue>* IpcManager::GetThreadedQueue(Destination destination) { - return destination == Destination::Client ? threaded_queue_for_client_.get() : threaded_queue_for_server_.get(); +ThreadedQueue>* IpcManager::GetThreadedQueue( + Destination destination) { + return destination == Destination::Client ? threaded_queue_for_client_.get() + : threaded_queue_for_server_.get(); } void IpcManager::SendOutMessageToClient(IpcId id, lsBaseOutMessage& response) { @@ -26,15 +28,19 @@ void IpcManager::SendOutMessageToClient(IpcId id, lsBaseOutMessage& response) { GetThreadedQueue(Destination::Client)->Enqueue(std::move(out)); } -void IpcManager::SendMessage(Destination destination, std::unique_ptr message) { +void IpcManager::SendMessage(Destination destination, + std::unique_ptr message) { GetThreadedQueue(destination)->Enqueue(std::move(message)); } -std::vector> IpcManager::GetMessages(Destination destination) { +std::vector> IpcManager::GetMessages( + Destination destination) { return GetThreadedQueue(destination)->DequeueAll(); } IpcManager::IpcManager(MultiQueueWaiter* waiter) { - threaded_queue_for_client_ = MakeUnique>>(waiter); - threaded_queue_for_server_ = MakeUnique>>(waiter); + threaded_queue_for_client_ = + MakeUnique>>(waiter); + threaded_queue_for_server_ = + MakeUnique>>(waiter); } \ No newline at end of file diff --git a/src/ipc_manager.h b/src/ipc_manager.h index 8f089030..34be8b5d 100644 --- a/src/ipc_manager.h +++ b/src/ipc_manager.h @@ -11,21 +11,24 @@ struct IpcManager { static IpcManager* instance(); static void CreateInstance(MultiQueueWaiter* waiter); - std::unique_ptr>> threaded_queue_for_client_; - std::unique_ptr>> threaded_queue_for_server_; + std::unique_ptr>> + threaded_queue_for_client_; + std::unique_ptr>> + threaded_queue_for_server_; - enum class Destination { - Client, Server - }; + enum class Destination { Client, Server }; - ThreadedQueue>* GetThreadedQueue(Destination destination); + ThreadedQueue>* GetThreadedQueue( + Destination destination); void SendOutMessageToClient(IpcId id, lsBaseOutMessage& response); - void SendMessage(Destination destination, std::unique_ptr message); + void SendMessage(Destination destination, + std::unique_ptr message); - std::vector> GetMessages(Destination destination); + std::vector> GetMessages( + Destination destination); -private: + private: IpcManager(MultiQueueWaiter* waiter); }; diff --git a/src/language_server_api.cc b/src/language_server_api.cc index c25b0af7..ea4c821d 100644 --- a/src/language_server_api.cc +++ b/src/language_server_api.cc @@ -8,8 +8,7 @@ void Reflect(Writer& visitor, lsRequestId& value) { if (value.id0) { Reflect(visitor, value.id0.value()); - } - else { + } else { Reflect(visitor, value.id1.value()); } } @@ -26,7 +25,8 @@ void Reflect(Reader& visitor, lsRequestId& id) { MessageRegistry* MessageRegistry::instance_ = nullptr; // Reads a JsonRpc message. |read| returns the next input character. -optional ReadJsonRpcContentFrom(std::function()> read) { +optional ReadJsonRpcContentFrom( + std::function()> read) { // Read the content length. It is terminated by the "\r\n" sequence. int exit_seq = 0; std::string stringified_content_length; @@ -38,14 +38,17 @@ optional ReadJsonRpcContentFrom(std::function()> rea } char c = *opt_c; - if (exit_seq == 0 && c == '\r') ++exit_seq; - if (exit_seq == 1 && c == '\n') break; + if (exit_seq == 0 && c == '\r') + ++exit_seq; + if (exit_seq == 1 && c == '\n') + break; stringified_content_length += c; } const char* kContentLengthStart = "Content-Length: "; assert(StartsWith(stringified_content_length, kContentLengthStart)); - int content_length = atoi(stringified_content_length.c_str() + strlen(kContentLengthStart)); + int content_length = + atoi(stringified_content_length.c_str() + strlen(kContentLengthStart)); // There is always a "\r\n" sequence before the actual content. auto expect_char = [&](char expected) { @@ -74,8 +77,8 @@ optional ReadJsonRpcContentFrom(std::function()> rea TEST_SUITE("FindIncludeLine"); -std::function()> - MakeContentReader(std::string* content, bool can_be_empty) { +std::function()> MakeContentReader(std::string* content, + bool can_be_empty) { return [content, can_be_empty]() -> optional { if (!can_be_empty) REQUIRE(!content->empty()); @@ -106,7 +109,8 @@ TEST_CASE("ReadContentFromSource") { REQUIRE(parse_incorrect("ggg") == optional()); REQUIRE(parse_incorrect("Content-Length: 0\r\n") == optional()); - REQUIRE(parse_incorrect("Content-Length: 5\r\n\r\nab") == optional()); + REQUIRE(parse_incorrect("Content-Length: 5\r\n\r\nab") == + optional()); } TEST_SUITE_END(); @@ -125,7 +129,8 @@ optional ReadCharFromStdinBlocking() { } std::unique_ptr MessageRegistry::ReadMessageFromStdin() { - optional content = ReadJsonRpcContentFrom(&ReadCharFromStdinBlocking); + optional content = + ReadJsonRpcContentFrom(&ReadCharFromStdinBlocking); if (!content) { LOG_S(FATAL) << "Failed to read JsonRpc input; exiting"; exit(1); @@ -139,7 +144,8 @@ std::unique_ptr MessageRegistry::ReadMessageFromStdin() { } std::unique_ptr MessageRegistry::Parse(Reader& visitor) { - if (!visitor.HasMember("jsonrpc") || std::string(visitor["jsonrpc"].GetString()) != "2.0") { + if (!visitor.HasMember("jsonrpc") || + std::string(visitor["jsonrpc"].GetString()) != "2.0") { std::cerr << "Bad or missing jsonrpc version" << std::endl; exit(1); } @@ -148,7 +154,8 @@ std::unique_ptr MessageRegistry::Parse(Reader& visitor) { ReflectMember(visitor, "method", method); if (allocators.find(method) == allocators.end()) { - LOG_S(ERROR) << "Unable to find registered handler for method \"" << method << "\"" << std::endl; + LOG_S(ERROR) << "Unable to find registered handler for method \"" << method + << "\"" << std::endl; return nullptr; } @@ -196,8 +203,9 @@ void lsDocumentUri::SetPath(const std::string& path) { raw_uri = path; size_t index = raw_uri.find(":"); - if (index == 1) { // widows drive letters must always be 1 char - raw_uri.replace(raw_uri.begin() + index, raw_uri.begin() + index + 1, "%3A"); + if (index == 1) { // widows drive letters must always be 1 char + raw_uri.replace(raw_uri.begin() + index, raw_uri.begin() + index + 1, + "%3A"); } raw_uri = ReplaceAll(raw_uri, " ", "%20"); @@ -210,7 +218,7 @@ void lsDocumentUri::SetPath(const std::string& path) { #else raw_uri = "file://" + raw_uri; #endif - //std::cerr << "Set uri to " << raw_uri << " from " << path; + // std::cerr << "Set uri to " << raw_uri << " from " << path; } std::string lsDocumentUri::GetPath() const { @@ -242,14 +250,15 @@ std::string lsDocumentUri::GetPath() const { std::replace(result.begin(), result.end(), '\\', '/'); #if defined(_WIN32) - //std::transform(result.begin(), result.end(), result.begin(), ::tolower); + // std::transform(result.begin(), result.end(), result.begin(), ::tolower); #endif return result; } lsPosition::lsPosition() {} -lsPosition::lsPosition(int line, int character) : line(line), character(character) {} +lsPosition::lsPosition(int line, int character) + : line(line), character(character) {} bool lsPosition::operator==(const lsPosition& other) const { return line == other.line && character == other.character; @@ -267,7 +276,8 @@ bool lsRange::operator==(const lsRange& other) const { } lsLocation::lsLocation() {} -lsLocation::lsLocation(lsDocumentUri uri, lsRange range) : uri(uri), range(range) {} +lsLocation::lsLocation(lsDocumentUri uri, lsRange range) + : uri(uri), range(range) {} bool lsLocation::operator==(const lsLocation& other) const { return uri == other.uri && range == other.range; @@ -297,15 +307,15 @@ void Reflect(Reader& reader, lsInitializeParams::lsTrace& value) { void Reflect(Writer& writer, lsInitializeParams::lsTrace& value) { switch (value) { - case lsInitializeParams::lsTrace::Off: - writer.String("off"); - break; - case lsInitializeParams::lsTrace::Messages: - writer.String("messages"); - break; - case lsInitializeParams::lsTrace::Verbose: - writer.String("verbose"); - break; + case lsInitializeParams::lsTrace::Off: + writer.String("off"); + break; + case lsInitializeParams::lsTrace::Messages: + writer.String("messages"); + break; + case lsInitializeParams::lsTrace::Verbose: + writer.String("verbose"); + break; } } diff --git a/src/language_server_api.h b/src/language_server_api.h index 547b696b..336f48f7 100644 --- a/src/language_server_api.h +++ b/src/language_server_api.h @@ -14,8 +14,8 @@ #include #include -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -79,10 +79,11 @@ struct MessageRegistry { static MessageRegistry* instance_; static MessageRegistry* instance(); - using Allocator = std::function(Reader& visitor)>; + using Allocator = + std::function(Reader& visitor)>; std::unordered_map allocators; - template + template void Register() { std::string method_name = IpcIdToString(T::kIpcId); allocators[method_name] = [](Reader& visitor) { @@ -96,13 +97,12 @@ struct MessageRegistry { std::unique_ptr Parse(Reader& visitor); }; - struct lsBaseOutMessage { virtual ~lsBaseOutMessage(); virtual void Write(std::ostream& out) = 0; }; -template +template struct lsOutMessage : lsBaseOutMessage { // All derived types need to reflect on the |jsonrpc| member. std::string jsonrpc = "2.0"; @@ -115,7 +115,7 @@ struct lsOutMessage : lsBaseOutMessage { Reflect(writer, *that); out << "Content-Length: " << output.GetSize(); - out << (char)13 << char(10) << char(13) << char(10); // CRLFCRLF + out << (char)13 << char(10) << char(13) << char(10); // CRLFCRLF out << output.GetString(); out.flush(); } @@ -216,12 +216,11 @@ struct lsDocumentUri { }; MAKE_HASHABLE(lsDocumentUri, t.raw_uri); -template +template void Reflect(TVisitor& visitor, lsDocumentUri& value) { Reflect(visitor, value.raw_uri); } - struct lsPosition { lsPosition(); lsPosition(int line, int character); @@ -291,7 +290,7 @@ struct lsSymbolInformation { }; MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, location, containerName); -template +template struct lsCommand { // Title of the command (ie, 'save') std::string title; @@ -302,7 +301,7 @@ struct lsCommand { // MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY. T arguments; }; -template +template void Reflect(TVisitor& visitor, lsCommand& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(title); @@ -311,7 +310,7 @@ void Reflect(TVisitor& visitor, lsCommand& value) { REFLECT_MEMBER_END(); } -template +template struct lsCodeLens { // The range in which this code lens is valid. Should only span a single line. lsRange range; @@ -321,7 +320,7 @@ struct lsCodeLens { // a code lens and a code lens resolve request. TData data; }; -template +template void Reflect(TVisitor& visitor, lsCodeLens& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(range); @@ -377,7 +376,8 @@ enum class lsInsertTextFormat { // the end of the snippet. Placeholders with equal identifiers are linked, // that is typing in one will update others too. // - // See also: https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md + // See also: + // https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md Snippet = 2 }; MAKE_REFLECT_TYPE_PROXY(lsInsertTextFormat, int); @@ -406,7 +406,8 @@ enum class lsCompletionItemKind { MAKE_REFLECT_TYPE_PROXY(lsCompletionItemKind, int); struct lsCompletionItem { - // A set of function parameters. Used internally for signature help. Not sent to vscode. + // A set of function parameters. Used internally for signature help. Not sent + // to vscode. std::vector parameters_; // The label of this completion item. By default @@ -431,21 +432,21 @@ struct lsCompletionItem { // A string that should be used when filtering a set of // completion items. When `falsy` the label is used. - //std::string filterText; + // std::string filterText; // A string that should be inserted a document when selecting // this completion. When `falsy` the label is used. std::string insertText; - // The format of the insert text. The format applies to both the `insertText` property - // and the `newText` property of a provided `textEdit`. + // The format of the insert text. The format applies to both the `insertText` + // property and the `newText` property of a provided `textEdit`. lsInsertTextFormat insertTextFormat = lsInsertTextFormat::Snippet; - // An edit which is applied to a document when selecting this completion. When an edit is provided the value of - // `insertText` is ignored. + // An edit which is applied to a document when selecting this completion. When + // an edit is provided the value of `insertText` is ignored. // - // *Note:* The range of the edit must be a single line range and it must contain the position at which completion - // has been requested. + // *Note:* The range of the edit must be a single line range and it must + // contain the position at which completion has been requested. optional textEdit; // An optional array of additional text edits that are applied when @@ -453,10 +454,9 @@ struct lsCompletionItem { // nor with themselves. // std::vector additionalTextEdits; - // An optional command that is executed *after* inserting this completion. *Note* that - // additional modifications to the current document should be described with the - // additionalTextEdits-property. - // Command command; + // An optional command that is executed *after* inserting this completion. + // *Note* that additional modifications to the current document should be + // described with the additionalTextEdits-property. Command command; // An data entry field that is preserved on a completion item between // a completion and a completion resolve request. @@ -468,14 +468,14 @@ struct lsCompletionItem { const std::string& InsertedContent() const; }; MAKE_REFLECT_STRUCT(lsCompletionItem, - label, - kind, - detail, - documentation, - sortText, - insertText, - insertTextFormat, - textEdit); + label, + kind, + detail, + documentation, + sortText, + insertText, + insertTextFormat, + textEdit); struct lsTextDocumentItem { // The text document's URI. @@ -505,7 +505,7 @@ MAKE_REFLECT_STRUCT(lsTextDocumentEdit, textDocument, edits); struct lsWorkspaceEdit { // Holds changes to existing resources. // changes ? : { [uri:string]: TextEdit[]; }; - //std::unordered_map> changes; + // std::unordered_map> changes; // An array of `TextDocumentEdit`s to express changes to specific a specific // version of a text document. Whether a client supports versioned document @@ -529,10 +529,10 @@ MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind, int); // special attention. Usually a document highlight is visualized by changing // the background color of its range. struct lsDocumentHighlight { - // The range this highlight applies to. - lsRange range; + // The range this highlight applies to. + lsRange range; - // The highlight kind, default is DocumentHighlightKind.Text. + // The highlight kind, default is DocumentHighlightKind.Text. lsDocumentHighlightKind kind = lsDocumentHighlightKind::Text; }; MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind); @@ -572,7 +572,6 @@ struct lsDiagnostic { }; MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, source, message); - // TODO: DocumentFilter // TODO: DocumentSelector @@ -687,17 +686,17 @@ struct lsWorkspaceClientCapabilites { // Capabilities specific to `WorkspaceEdit`s optional workspaceEdit; - struct lsGenericDynamicReg { // Did foo notification supports dynamic registration. optional dynamicRegistration; }; - - // Capabilities specific to the `workspace/didChangeConfiguration` notification. + // Capabilities specific to the `workspace/didChangeConfiguration` + // notification. optional didChangeConfiguration; - // Capabilities specific to the `workspace/didChangeWatchedFiles` notification. + // Capabilities specific to the `workspace/didChangeWatchedFiles` + // notification. optional didChangeWatchedFiles; // Capabilities specific to the `workspace/symbol` request. @@ -707,17 +706,17 @@ struct lsWorkspaceClientCapabilites { optional executeCommand; }; -MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsWorkspaceEdit, documentChanges); -MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsGenericDynamicReg, dynamicRegistration); +MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsWorkspaceEdit, + documentChanges); +MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsGenericDynamicReg, + dynamicRegistration); MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites, - applyEdit, - workspaceEdit, - didChangeConfiguration, - didChangeWatchedFiles, - symbol, - executeCommand); - - + applyEdit, + workspaceEdit, + didChangeConfiguration, + didChangeWatchedFiles, + symbol, + executeCommand); // Text document specific client capabilities. struct lsTextDocumentClientCapabilities { @@ -810,27 +809,39 @@ struct lsTextDocumentClientCapabilities { optional rename; }; -MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsSynchronization, dynamicRegistration, willSave, willSaveWaitUntil, didSave); -MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsCompletion, dynamicRegistration, completionItem); -MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsCompletion::lsCompletionItem, snippetSupport); -MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsGenericDynamicReg, dynamicRegistration); -MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::CodeLensRegistrationOptions, dynamicRegistration, resolveProvider); +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsSynchronization, + dynamicRegistration, + willSave, + willSaveWaitUntil, + didSave); +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsCompletion, + dynamicRegistration, + completionItem); +MAKE_REFLECT_STRUCT( + lsTextDocumentClientCapabilities::lsCompletion::lsCompletionItem, + snippetSupport); +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsGenericDynamicReg, + dynamicRegistration); +MAKE_REFLECT_STRUCT( + lsTextDocumentClientCapabilities::CodeLensRegistrationOptions, + dynamicRegistration, + resolveProvider); MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, - synchronization, - completion, - hover, - signatureHelp, - references, - documentHighlight, - documentSymbol, - formatting, - rangeFormatting, - onTypeFormatting, - definition, - codeAction, - codeLens, - documentLink, - rename); + synchronization, + completion, + hover, + signatureHelp, + references, + documentHighlight, + documentSymbol, + formatting, + rangeFormatting, + onTypeFormatting, + definition, + codeAction, + codeLens, + documentLink, + rename); struct lsClientCapabilities { // Workspace specific client capabilities. @@ -840,8 +851,8 @@ struct lsClientCapabilities { optional textDocument; /** - * Experimental client capabilities. - */ + * Experimental client capabilities. + */ // experimental?: any; // TODO }; MAKE_REFLECT_STRUCT(lsClientCapabilities, workspace, textDocument); @@ -849,7 +860,8 @@ MAKE_REFLECT_STRUCT(lsClientCapabilities, workspace, textDocument); struct lsInitializeParams { // The process Id of the parent process that started // the server. Is null if the process has not been started by another process. - // If the parent process is not alive then the server should exit (see exit notification) its process. + // If the parent process is not alive then the server should exit (see exit + // notification) its process. optional processId; // The rootPath of the workspace. Is null @@ -871,9 +883,9 @@ struct lsInitializeParams { enum class lsTrace { // NOTE: serialized as a string, one of 'off' | 'messages' | 'verbose'; - Off, // off - Messages, // messages - Verbose // verbose + Off, // off + Messages, // messages + Verbose // verbose }; // The initial trace setting. If omitted trace is disabled ('off'). @@ -881,8 +893,13 @@ struct lsInitializeParams { }; void Reflect(Reader& reader, lsInitializeParams::lsTrace& value); void Reflect(Writer& writer, lsInitializeParams::lsTrace& value); -MAKE_REFLECT_STRUCT(lsInitializeParams, processId, rootPath, rootUri, initializationOptions, capabilities, trace); - +MAKE_REFLECT_STRUCT(lsInitializeParams, + processId, + rootPath, + rootUri, + initializationOptions, + capabilities, + trace); struct lsInitializeError { // Indicates whether the client should retry to send the @@ -892,7 +909,8 @@ struct lsInitializeError { }; MAKE_REFLECT_STRUCT(lsInitializeError, retry); -// Defines how the host (editor) should sync document changes to the language server. +// Defines how the host (editor) should sync document changes to the language +// server. enum class lsTextDocumentSyncKind { // Documents should not be synced at all. None = 0, @@ -941,7 +959,9 @@ struct lsDocumentOnTypeFormattingOptions { // More trigger characters. NonElidedVector moreTriggerCharacter; }; -MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter, moreTriggerCharacter); +MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, + firstTriggerCharacter, + moreTriggerCharacter); // Document link options struct lsDocumentLinkOptions { @@ -967,8 +987,8 @@ MAKE_REFLECT_STRUCT(lsSaveOptions, includeText); struct lsTextDocumentSyncOptions { // Open and close notifications are sent to the server. bool openClose = false; - // Change notificatins are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full - // and TextDocumentSyncKindIncremental. + // Change notificatins are sent to the server. See TextDocumentSyncKind.None, + // TextDocumentSyncKind.Full and TextDocumentSyncKindIncremental. lsTextDocumentSyncKind change = lsTextDocumentSyncKind::Incremental; // Will save notifications are sent to the server. optional willSave; @@ -977,11 +997,17 @@ struct lsTextDocumentSyncOptions { // Save notifications are sent to the server. optional save; }; -MAKE_REFLECT_STRUCT(lsTextDocumentSyncOptions, openClose, change, willSave, willSaveWaitUntil, save); +MAKE_REFLECT_STRUCT(lsTextDocumentSyncOptions, + openClose, + change, + willSave, + willSaveWaitUntil, + save); struct lsServerCapabilities { - // Defines how text documents are synced. Is either a detailed structure defining each notification or - // for backwards compatibility the TextDocumentSyncKind number. + // Defines how text documents are synced. Is either a detailed structure + // defining each notification or for backwards compatibility the + // TextDocumentSyncKind number. // TODO: It seems like the new API is broken and doesn't work. // optional textDocumentSync; lsTextDocumentSyncKind textDocumentSync; @@ -1020,23 +1046,23 @@ struct lsServerCapabilities { optional executeCommandProvider; }; MAKE_REFLECT_STRUCT(lsServerCapabilities, - textDocumentSync, - hoverProvider, - completionProvider, - signatureHelpProvider, - definitionProvider, - referencesProvider, - documentHighlightProvider, - documentSymbolProvider, - workspaceSymbolProvider, - codeActionProvider, - codeLensProvider, - documentFormattingProvider, - documentRangeFormattingProvider, - documentOnTypeFormattingProvider, - renameProvider, - documentLinkProvider, - executeCommandProvider); + textDocumentSync, + hoverProvider, + completionProvider, + signatureHelpProvider, + definitionProvider, + referencesProvider, + documentHighlightProvider, + documentSymbolProvider, + workspaceSymbolProvider, + codeActionProvider, + codeLensProvider, + documentFormattingProvider, + documentRangeFormattingProvider, + documentOnTypeFormattingProvider, + renameProvider, + documentLinkProvider, + executeCommandProvider); struct Ipc_InitializeRequest : public IpcMessage { const static IpcId kIpcId = IpcId::Initialize; @@ -1056,7 +1082,8 @@ struct Out_InitializeResponse : public lsOutMessage { MAKE_REFLECT_STRUCT(Out_InitializeResponse::InitializeResult, capabilities); MAKE_REFLECT_STRUCT(Out_InitializeResponse, jsonrpc, id, result); -struct Ipc_InitializedNotification : public IpcMessage { +struct Ipc_InitializedNotification + : public IpcMessage { const static IpcId kIpcId = IpcId::Initialized; lsRequestId id; @@ -1136,11 +1163,6 @@ struct Out_Error : public lsOutMessage { MAKE_REFLECT_STRUCT(Out_Error::lsResponseError, code, message); MAKE_REFLECT_STRUCT(Out_Error, jsonrpc, id, error); - - - - - // Cancel an existing request. struct Ipc_CancelRequest : public IpcMessage { static const IpcId kIpcId = IpcId::CancelRequest; @@ -1148,10 +1170,6 @@ struct Ipc_CancelRequest : public IpcMessage { }; MAKE_REFLECT_STRUCT(Ipc_CancelRequest, id); - - - - // Open, update, close file struct Ipc_TextDocumentDidOpen : public IpcMessage { struct Params { @@ -1163,7 +1181,8 @@ struct Ipc_TextDocumentDidOpen : public IpcMessage { }; MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidOpen::Params, textDocument); MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidOpen, params); -struct Ipc_TextDocumentDidChange : public IpcMessage { +struct Ipc_TextDocumentDidChange + : public IpcMessage { struct lsTextDocumentContentChangeEvent { // The range of the document that changed. lsRange range; @@ -1181,8 +1200,13 @@ struct Ipc_TextDocumentDidChange : public IpcMessage const static IpcId kIpcId = IpcId::TextDocumentDidChange; Params params; }; -MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidChange::lsTextDocumentContentChangeEvent, range, rangeLength, text); -MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidChange::Params, textDocument, contentChanges); +MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidChange::lsTextDocumentContentChangeEvent, + range, + rangeLength, + text); +MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidChange::Params, + textDocument, + contentChanges); MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidChange, params); struct Ipc_TextDocumentDidClose : public IpcMessage { struct Params { @@ -1195,7 +1219,6 @@ struct Ipc_TextDocumentDidClose : public IpcMessage { MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidClose::Params, textDocument); MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidClose, params); - struct Ipc_TextDocumentDidSave : public IpcMessage { struct Params { // The document that was saved. @@ -1212,10 +1235,9 @@ struct Ipc_TextDocumentDidSave : public IpcMessage { MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidSave::Params, textDocument); MAKE_REFLECT_STRUCT(Ipc_TextDocumentDidSave, params); - - // Diagnostics -struct Out_TextDocumentPublishDiagnostics : public lsOutMessage { +struct Out_TextDocumentPublishDiagnostics + : public lsOutMessage { struct Params { // The URI for which diagnostic information is reported. lsDocumentUri uri; @@ -1226,7 +1248,7 @@ struct Out_TextDocumentPublishDiagnostics : public lsOutMessage +template void Reflect(TVisitor& visitor, Out_TextDocumentPublishDiagnostics& value) { std::string method = "textDocument/publishDiagnostics"; REFLECT_MEMBER_START(); @@ -1235,9 +1257,9 @@ void Reflect(TVisitor& visitor, Out_TextDocumentPublishDiagnostics& value) { REFLECT_MEMBER(params); REFLECT_MEMBER_END(); } -MAKE_REFLECT_STRUCT(Out_TextDocumentPublishDiagnostics::Params, uri, diagnostics); - - +MAKE_REFLECT_STRUCT(Out_TextDocumentPublishDiagnostics::Params, + uri, + diagnostics); // Rename struct Ipc_TextDocumentRename : public IpcMessage { @@ -1258,7 +1280,10 @@ struct Ipc_TextDocumentRename : public IpcMessage { lsRequestId id; Params params; }; -MAKE_REFLECT_STRUCT(Ipc_TextDocumentRename::Params, textDocument, position, newName); +MAKE_REFLECT_STRUCT(Ipc_TextDocumentRename::Params, + textDocument, + position, + newName); MAKE_REFLECT_STRUCT(Ipc_TextDocumentRename, id, params); struct Out_TextDocumentRename : public lsOutMessage { lsRequestId id; @@ -1266,10 +1291,6 @@ struct Out_TextDocumentRename : public lsOutMessage { }; MAKE_REFLECT_STRUCT(Out_TextDocumentRename, jsonrpc, id, result); - - - - // Code completion struct Ipc_TextDocumentComplete : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentCompletion; @@ -1286,14 +1307,16 @@ struct lsTextDocumentCompleteResult { NonElidedVector items; }; MAKE_REFLECT_STRUCT(lsTextDocumentCompleteResult, isIncomplete, items); -struct Out_TextDocumentComplete : public lsOutMessage { +struct Out_TextDocumentComplete + : public lsOutMessage { lsRequestId id; lsTextDocumentCompleteResult result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentComplete, jsonrpc, id, result); // Signature help. -struct Ipc_TextDocumentSignatureHelp : public IpcMessage { +struct Ipc_TextDocumentSignatureHelp + : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentSignatureHelp; lsRequestId id; @@ -1353,36 +1376,44 @@ struct lsSignatureHelp { // active signature does have any. optional activeParameter; }; -MAKE_REFLECT_STRUCT(lsSignatureHelp, signatures, activeSignature, activeParameter); -struct Out_TextDocumentSignatureHelp : public lsOutMessage { +MAKE_REFLECT_STRUCT(lsSignatureHelp, + signatures, + activeSignature, + activeParameter); +struct Out_TextDocumentSignatureHelp + : public lsOutMessage { lsRequestId id; lsSignatureHelp result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentSignatureHelp, jsonrpc, id, result); // Goto definition -struct Ipc_TextDocumentDefinition : public IpcMessage { +struct Ipc_TextDocumentDefinition + : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentDefinition; lsRequestId id; lsTextDocumentPositionParams params; }; MAKE_REFLECT_STRUCT(Ipc_TextDocumentDefinition, id, params); -struct Out_TextDocumentDefinition : public lsOutMessage { +struct Out_TextDocumentDefinition + : public lsOutMessage { lsRequestId id; NonElidedVector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result); // Document highlight -struct Ipc_TextDocumentDocumentHighlight : public IpcMessage { +struct Ipc_TextDocumentDocumentHighlight + : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentDocumentHighlight; lsRequestId id; lsTextDocumentPositionParams params; }; MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentHighlight, id, params); -struct Out_TextDocumentDocumentHighlight : public lsOutMessage { +struct Out_TextDocumentDocumentHighlight + : public lsOutMessage { lsRequestId id; NonElidedVector result; }; @@ -1409,7 +1440,8 @@ MAKE_REFLECT_STRUCT(Out_TextDocumentHover::Result, contents, range); MAKE_REFLECT_STRUCT(Out_TextDocumentHover, jsonrpc, id, result); // References -struct Ipc_TextDocumentReferences : public IpcMessage { +struct Ipc_TextDocumentReferences + : public IpcMessage { struct lsReferenceContext { // Include the declaration of the current symbol. bool includeDeclaration; @@ -1425,41 +1457,52 @@ struct Ipc_TextDocumentReferences : public IpcMessage { +struct Out_TextDocumentReferences + : public lsOutMessage { lsRequestId id; NonElidedVector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentReferences, jsonrpc, id, result); // Code action -struct Ipc_TextDocumentCodeAction : public IpcMessage { +struct Ipc_TextDocumentCodeAction + : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentCodeAction; // Contains additional diagnostic information about the context in which // a code action is run. struct lsCodeActionContext { - // An array of diagnostics. - NonElidedVector diagnostics; + // An array of diagnostics. + NonElidedVector diagnostics; }; // Params for the CodeActionRequest struct lsCodeActionParams { - // The document in which the command was invoked. - lsTextDocumentIdentifier textDocument; - // The range for which the command was invoked. + // The document in which the command was invoked. + lsTextDocumentIdentifier textDocument; + // The range for which the command was invoked. lsRange range; - // Context carrying additional information. + // Context carrying additional information. lsCodeActionContext context; }; lsRequestId id; lsCodeActionParams params; }; -MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction::lsCodeActionContext, diagnostics); -MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction::lsCodeActionParams, textDocument, range, context); +MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction::lsCodeActionContext, + diagnostics); +MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction::lsCodeActionParams, + textDocument, + range, + context); MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeAction, id, params); -struct Out_TextDocumentCodeAction : public lsOutMessage { +struct Out_TextDocumentCodeAction + : public lsOutMessage { struct CommandArgs { lsDocumentUri textDocumentUri; NonElidedVector edits; @@ -1469,7 +1512,9 @@ struct Out_TextDocumentCodeAction : public lsOutMessage result; }; -MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(Out_TextDocumentCodeAction::CommandArgs, textDocumentUri, edits); +MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(Out_TextDocumentCodeAction::CommandArgs, + textDocumentUri, + edits); MAKE_REFLECT_STRUCT(Out_TextDocumentCodeAction, jsonrpc, id, result); // List symbols in a document. @@ -1477,21 +1522,24 @@ struct lsDocumentSymbolParams { lsTextDocumentIdentifier textDocument; }; MAKE_REFLECT_STRUCT(lsDocumentSymbolParams, textDocument); -struct Ipc_TextDocumentDocumentSymbol : public IpcMessage { +struct Ipc_TextDocumentDocumentSymbol + : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentDocumentSymbol; lsRequestId id; lsDocumentSymbolParams params; }; MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentSymbol, id, params); -struct Out_TextDocumentDocumentSymbol : public lsOutMessage { +struct Out_TextDocumentDocumentSymbol + : public lsOutMessage { lsRequestId id; NonElidedVector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentSymbol, jsonrpc, id, result); // List links a document -struct Ipc_TextDocumentDocumentLink : public IpcMessage { +struct Ipc_TextDocumentDocumentLink + : public IpcMessage { const static IpcId kIpcId = IpcId::TextDocumentDocumentLink; struct DocumentLinkParams { @@ -1502,24 +1550,25 @@ struct Ipc_TextDocumentDocumentLink : public IpcMessage target; + // The range this link applies to. + lsRange range; + // The uri this link points to. If missing a resolve request is sent later. + optional target; }; MAKE_REFLECT_STRUCT(lsDocumentLink, range, target); -struct Out_TextDocumentDocumentLink : public lsOutMessage { +struct Out_TextDocumentDocumentLink + : public lsOutMessage { lsRequestId id; NonElidedVector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentLink, jsonrpc, id, result); - // List code lens in a document. struct lsDocumentCodeLensParams { lsTextDocumentIdentifier textDocument; @@ -1541,9 +1590,11 @@ struct Ipc_TextDocumentCodeLens : public IpcMessage { lsDocumentCodeLensParams params; }; MAKE_REFLECT_STRUCT(Ipc_TextDocumentCodeLens, id, params); -struct Out_TextDocumentCodeLens : public lsOutMessage { +struct Out_TextDocumentCodeLens + : public lsOutMessage { lsRequestId id; - NonElidedVector> result; + NonElidedVector> + result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentCodeLens, jsonrpc, id, result); struct Ipc_CodeLensResolve : public IpcMessage { @@ -1577,12 +1628,7 @@ struct Out_WorkspaceSymbol : public lsOutMessage { MAKE_REFLECT_STRUCT(Out_WorkspaceSymbol, jsonrpc, id, result); // Show a message to the user. -enum class lsMessageType : int { - Error = 1, - Warning = 2, - Info = 3, - Log = 4 -}; +enum class lsMessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 }; MAKE_REFLECT_TYPE_PROXY(lsMessageType, int) struct Out_ShowLogMessageParams { lsMessageType type = lsMessageType::Error; @@ -1590,15 +1636,13 @@ struct Out_ShowLogMessageParams { }; MAKE_REFLECT_STRUCT(Out_ShowLogMessageParams, type, message); struct Out_ShowLogMessage : public lsOutMessage { - enum class DisplayType { - Show, Log - }; + enum class DisplayType { Show, Log }; DisplayType display_type = DisplayType::Show; std::string method(); Out_ShowLogMessageParams params; }; -template +template void Reflect(TVisitor& visitor, Out_ShowLogMessage& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(jsonrpc); @@ -1608,8 +1652,8 @@ void Reflect(TVisitor& visitor, Out_ShowLogMessage& value) { REFLECT_MEMBER_END(); } - -struct Out_CquerySetInactiveRegion : public lsOutMessage { +struct Out_CquerySetInactiveRegion + : public lsOutMessage { struct Params { lsDocumentUri uri; NonElidedVector inactiveRegions; @@ -1620,7 +1664,6 @@ struct Out_CquerySetInactiveRegion : public lsOutMessage { const static IpcId kIpcId = IpcId::CqueryFreshenIndex; lsRequestId id; @@ -1628,13 +1671,15 @@ struct Ipc_CqueryFreshenIndex : public IpcMessage { MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, id); // Type Hierarchy Tree -struct Ipc_CqueryTypeHierarchyTree : public IpcMessage { +struct Ipc_CqueryTypeHierarchyTree + : public IpcMessage { const static IpcId kIpcId = IpcId::CqueryTypeHierarchyTree; lsRequestId id; lsTextDocumentPositionParams params; }; MAKE_REFLECT_STRUCT(Ipc_CqueryTypeHierarchyTree, id, params); -struct Out_CqueryTypeHierarchyTree : public lsOutMessage { +struct Out_CqueryTypeHierarchyTree + : public lsOutMessage { struct TypeEntry { std::string name; optional location; @@ -1643,11 +1688,15 @@ struct Out_CqueryTypeHierarchyTree : public lsOutMessage result; }; -MAKE_REFLECT_STRUCT(Out_CqueryTypeHierarchyTree::TypeEntry, name, location, children); +MAKE_REFLECT_STRUCT(Out_CqueryTypeHierarchyTree::TypeEntry, + name, + location, + children); MAKE_REFLECT_STRUCT(Out_CqueryTypeHierarchyTree, jsonrpc, id, result); // Call Tree -struct Ipc_CqueryCallTreeInitial : public IpcMessage { +struct Ipc_CqueryCallTreeInitial + : public IpcMessage { const static IpcId kIpcId = IpcId::CqueryCallTreeInitial; lsRequestId id; lsTextDocumentPositionParams params; @@ -1664,9 +1713,7 @@ struct Ipc_CqueryCallTreeExpand : public IpcMessage { MAKE_REFLECT_STRUCT(Ipc_CqueryCallTreeExpand::Params, usr); MAKE_REFLECT_STRUCT(Ipc_CqueryCallTreeExpand, id, params); struct Out_CqueryCallTree : public lsOutMessage { - enum class CallType { - Direct = 0, Base = 1, Derived = 2 - }; + enum class CallType { Direct = 0, Base = 1, Derived = 2 }; struct CallEntry { std::string name; std::string usr; @@ -1679,7 +1726,12 @@ struct Out_CqueryCallTree : public lsOutMessage { NonElidedVector result; }; MAKE_REFLECT_TYPE_PROXY(Out_CqueryCallTree::CallType, int); -MAKE_REFLECT_STRUCT(Out_CqueryCallTree::CallEntry, name, usr, location, hasCallers, callType); +MAKE_REFLECT_STRUCT(Out_CqueryCallTree::CallEntry, + name, + usr, + location, + hasCallers, + callType); MAKE_REFLECT_STRUCT(Out_CqueryCallTree, jsonrpc, id, result); // Vars, Callers, Derived, GotoParent diff --git a/src/lex_utils.cc b/src/lex_utils.cc index a2ed2e69..5a8dd401 100644 --- a/src/lex_utils.cc +++ b/src/lex_utils.cc @@ -20,7 +20,9 @@ int GetOffsetForPosition(lsPosition position, const std::string& content) { return std::min(offset + position.character, content.size()); } -lsPosition CharPos(const std::string& search, char character, int character_offset) { +lsPosition CharPos(const std::string& search, + char character, + int character_offset) { lsPosition result; int index = 0; while (index < search.size()) { @@ -30,8 +32,7 @@ lsPosition CharPos(const std::string& search, char character, int character_offs if (c == '\n') { result.line += 1; result.character = 0; - } - else { + } else { result.character += 1; } ++index; @@ -75,7 +76,11 @@ optional ExtractQuotedRange(int line_number, const std::string& line) { return lsRange(lsPosition(line_number, start), lsPosition(line_number, end)); } -void LexFunctionDeclaration(const std::string& buffer_content, lsPosition declaration_spelling, optional type_name, std::string* insert_text, int* newlines_after_name) { +void LexFunctionDeclaration(const std::string& buffer_content, + lsPosition declaration_spelling, + optional type_name, + std::string* insert_text, + int* newlines_after_name) { int name_start = GetOffsetForPosition(declaration_spelling, buffer_content); bool parse_return_type = true; @@ -89,7 +94,8 @@ void LexFunctionDeclaration(const std::string& buffer_content, lsPosition declar ++name_end; } - std::string func_name = buffer_content.substr(name_start, name_end - name_start); + std::string func_name = + buffer_content.substr(name_start, name_end - name_start); if (func_name == *type_name || func_name == ("~" + *type_name)) parse_return_type = false; } @@ -163,8 +169,7 @@ std::string LexWordAroundPos(lsPosition position, const std::string& content) { char c = content[start - 1]; if (isalnum(c) || c == '_') { --start; - } - else { + } else { break; } } @@ -173,8 +178,7 @@ std::string LexWordAroundPos(lsPosition position, const std::string& content) { char c = content[end + 1]; if (isalnum(c) || c == '_') { ++end; - } - else { + } else { break; } } diff --git a/src/lex_utils.h b/src/lex_utils.h index ccb11416..89bbff05 100644 --- a/src/lex_utils.h +++ b/src/lex_utils.h @@ -4,18 +4,23 @@ #include - // Utility method to map |position| to an offset inside of |content|. int GetOffsetForPosition(lsPosition position, const std::string& content); // Utility method to find a position for the given character. -lsPosition CharPos(const std::string& search, char character, int character_offset = 0); +lsPosition CharPos(const std::string& search, + char character, + int character_offset = 0); bool ShouldRunIncludeCompletion(const std::string& line); // TODO: eliminate |line_number| param. optional ExtractQuotedRange(int line_number, const std::string& line); -void LexFunctionDeclaration(const std::string& buffer_content, lsPosition declaration_spelling, optional type_name, std::string* insert_text, int* newlines_after_name); +void LexFunctionDeclaration(const std::string& buffer_content, + lsPosition declaration_spelling, + optional type_name, + std::string* insert_text, + int* newlines_after_name); std::string LexWordAroundPos(lsPosition position, const std::string& content); diff --git a/src/libclangmm/Cursor.h b/src/libclangmm/Cursor.h index de27bcd1..6e0f9c8c 100644 --- a/src/libclangmm/Cursor.h +++ b/src/libclangmm/Cursor.h @@ -2,8 +2,9 @@ #define CURSOR_H_ #include -#include #include +#include + #include diff --git a/src/libclangmm/TranslationUnit.cc b/src/libclangmm/TranslationUnit.cc index a4dee975..4dedf342 100644 --- a/src/libclangmm/TranslationUnit.cc +++ b/src/libclangmm/TranslationUnit.cc @@ -1,13 +1,15 @@ #include "TranslationUnit.h" -#include "Utility.h" #include "../platform.h" #include "../utils.h" +#include "Utility.h" + -#include -#include #include +#include #include +#include + namespace clang { @@ -24,10 +26,12 @@ TranslationUnit::TranslationUnit(Index* index, for (const auto& arg : platform_args) args.push_back(arg.c_str()); - //std::cerr << "Parsing " << filepath << " with args " << StringJoin(args) << std::endl; + // std::cerr << "Parsing " << filepath << " with args " << StringJoin(args) << + // std::endl; - //cx_tu = clang_createTranslationUnitFromSourceFile( - // index->cx_index, filepath.c_str(), args.size(), args.data(), (unsigned)unsaved_files.size(), unsaved_files.data()); + // cx_tu = clang_createTranslationUnitFromSourceFile( + // index->cx_index, filepath.c_str(), args.size(), args.data(), + // (unsigned)unsaved_files.size(), unsaved_files.data()); CXErrorCode error_code = clang_parseTranslationUnit2( index->cx_index, filepath.c_str(), args.data(), (int)args.size(), @@ -38,20 +42,23 @@ TranslationUnit::TranslationUnit(Index* index, did_fail = false; break; case CXError_Failure: - std::cerr << "libclang generic failure for " << filepath << " with args " << StringJoin(args) << std::endl; + std::cerr << "libclang generic failure for " << filepath << " with args " + << StringJoin(args) << std::endl; did_fail = true; break; case CXError_Crashed: - std::cerr << "libclang crashed for " << filepath << " with args " << StringJoin(args) << std::endl; + std::cerr << "libclang crashed for " << filepath << " with args " + << StringJoin(args) << std::endl; did_fail = true; break; case CXError_InvalidArguments: - std::cerr << "libclang had invalid arguments for " << " with args " << StringJoin(args) << filepath - << std::endl; + std::cerr << "libclang had invalid arguments for " + << " with args " << StringJoin(args) << filepath << std::endl; did_fail = true; break; case CXError_ASTReadError: - std::cerr << "libclang had ast read error for " << filepath << " with args " << StringJoin(args) << std::endl; + std::cerr << "libclang had ast read error for " << filepath + << " with args " << StringJoin(args) << std::endl; did_fail = true; break; } @@ -63,9 +70,9 @@ TranslationUnit::~TranslationUnit() { void TranslationUnit::ReparseTranslationUnit( std::vector& unsaved) { - int error_code = - clang_reparseTranslationUnit(cx_tu, (unsigned)unsaved.size(), unsaved.data(), - clang_defaultReparseOptions(cx_tu)); + int error_code = clang_reparseTranslationUnit( + cx_tu, (unsigned)unsaved.size(), unsaved.data(), + clang_defaultReparseOptions(cx_tu)); switch (error_code) { case CXError_Success: did_fail = false; @@ -92,4 +99,4 @@ void TranslationUnit::ReparseTranslationUnit( Cursor TranslationUnit::document_cursor() const { return Cursor(clang_getTranslationUnitCursor(cx_tu)); } -} +} // namespace clang diff --git a/src/libclangmm/TranslationUnit.h b/src/libclangmm/TranslationUnit.h index c65e9980..cc53701d 100644 --- a/src/libclangmm/TranslationUnit.h +++ b/src/libclangmm/TranslationUnit.h @@ -1,8 +1,8 @@ #pragma once - -#include "Index.h" #include "Cursor.h" +#include "Index.h" + #include diff --git a/src/match.cc b/src/match.cc index 7ea202bf..c76729b4 100644 --- a/src/match.cc +++ b/src/match.cc @@ -21,33 +21,31 @@ optional Matcher::Create(const std::string& search) { try { Matcher m; m.regex_string = search; - m.regex = std::regex(search, - std::regex_constants::ECMAScript | - std::regex_constants::icase | - std::regex_constants::optimize - //std::regex_constants::nosubs + m.regex = std::regex( + search, std::regex_constants::ECMAScript | std::regex_constants::icase | + std::regex_constants::optimize + // std::regex_constants::nosubs ); return m; - } - catch (std::exception e) { + } catch (std::exception e) { Out_ShowLogMessage out; out.display_type = Out_ShowLogMessage::DisplayType::Show; out.params.type = lsMessageType::Error; - out.params.message = "cquery: Parsing EMCAScript regex \"" + search + "\" failed; " + e.what(); + out.params.message = "cquery: Parsing EMCAScript regex \"" + search + + "\" failed; " + e.what(); IpcManager::instance()->SendOutMessageToClient(IpcId::Cout, out); return nullopt; } } bool Matcher::IsMatch(const std::string& value) const { - //std::smatch match; - //return std::regex_match(value, match, regex); + // std::smatch match; + // return std::regex_match(value, match, regex); return std::regex_match(value, regex, std::regex_constants::match_any); } -GroupMatch::GroupMatch( - const std::vector& whitelist, - const std::vector& blacklist) { +GroupMatch::GroupMatch(const std::vector& whitelist, + const std::vector& blacklist) { for (const std::string& entry : whitelist) { optional m = Matcher::Create(entry); if (m) @@ -60,7 +58,8 @@ GroupMatch::GroupMatch( } } -bool GroupMatch::IsMatch(const std::string& value, std::string* match_failure_reason) const { +bool GroupMatch::IsMatch(const std::string& value, + std::string* match_failure_reason) const { for (const Matcher& m : whitelist) { if (!m.IsMatch(value)) { if (match_failure_reason) @@ -80,17 +79,16 @@ bool GroupMatch::IsMatch(const std::string& value, std::string* match_failure_re return true; } - TEST_SUITE("Matcher"); TEST_CASE("sanity") { - //Matcher m("abc"); + // Matcher m("abc"); // TODO: check case - //CHECK(m.IsMatch("abc")); - //CHECK(m.IsMatch("fooabc")); - //CHECK(m.IsMatch("abc")); - //CHECK(m.IsMatch("abcfoo")); - //CHECK(m.IsMatch("11a11b11c11")); + // CHECK(m.IsMatch("abc")); + // CHECK(m.IsMatch("fooabc")); + // CHECK(m.IsMatch("abc")); + // CHECK(m.IsMatch("abcfoo")); + // CHECK(m.IsMatch("11a11b11c11")); } TEST_SUITE_END(); diff --git a/src/match.h b/src/match.h index 467fefec..26629d8e 100644 --- a/src/match.h +++ b/src/match.h @@ -6,8 +6,8 @@ #include #include -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; struct Matcher { static optional Create(const std::string& search); @@ -23,7 +23,8 @@ struct GroupMatch { GroupMatch(const std::vector& whitelist, const std::vector& blacklist); - bool IsMatch(const std::string& value, std::string* match_failure_reason = nullptr) const; + bool IsMatch(const std::string& value, + std::string* match_failure_reason = nullptr) const; std::vector whitelist; std::vector blacklist; diff --git a/src/message_queue.cc b/src/message_queue.cc index ad84e5a8..8ca733e5 100644 --- a/src/message_queue.cc +++ b/src/message_queue.cc @@ -162,7 +162,6 @@ MessageQueue::MessageQueue(std::unique_ptr buffer, bool buffer_has_data) local_buffer_ = Buffer::Create(buffer_->capacity - sizeof(BufferMetadata)); memset(local_buffer_->data, 0, local_buffer_->capacity); - } void MessageQueue::Enqueue(const Message& message) { diff --git a/src/message_queue.h b/src/message_queue.h index ce4aa6b3..7919eb23 100644 --- a/src/message_queue.h +++ b/src/message_queue.h @@ -1,8 +1,9 @@ #pragma once -#include #include #include +#include + #include "buffer.h" diff --git a/src/options.cc b/src/options.cc index 9571b37d..63f47deb 100644 --- a/src/options.cc +++ b/src/options.cc @@ -3,7 +3,7 @@ #include std::unordered_map ParseOptions(int argc, - char** argv) { + char** argv) { std::unordered_map output; std::string previous_arg; @@ -14,14 +14,13 @@ std::unordered_map ParseOptions(int argc, if (arg[0] != '-') { if (previous_arg.size() == 0) { std::cerr << "Invalid arguments; switches must start with -" - << std::endl; + << std::endl; exit(1); } output[previous_arg] = arg; previous_arg = ""; - } - else { + } else { output[arg] = ""; previous_arg = arg; } @@ -31,6 +30,6 @@ std::unordered_map ParseOptions(int argc, } bool HasOption(const std::unordered_map& options, - const std::string& option) { + const std::string& option) { return options.find(option) != options.end(); } \ No newline at end of file diff --git a/src/options.h b/src/options.h index f13c739c..eec6f17e 100644 --- a/src/options.h +++ b/src/options.h @@ -2,10 +2,8 @@ #include -std::unordered_map ParseOptions( - int argc, - char** argv); +std::unordered_map ParseOptions(int argc, + char** argv); -bool HasOption( - const std::unordered_map& options, - const std::string& option); \ No newline at end of file +bool HasOption(const std::unordered_map& options, + const std::string& option); \ No newline at end of file diff --git a/src/performance.h b/src/performance.h index 201e0ed8..56c34880 100644 --- a/src/performance.h +++ b/src/performance.h @@ -22,8 +22,14 @@ struct PerformanceImportFile { // [indexer] create delta IndexUpdate object uint64_t index_make_delta = 0; // [querydb] update WorkingFile indexed file state - //uint64_t querydb_update_working_file = 0; + // uint64_t querydb_update_working_file = 0; // [querydb] apply IndexUpdate - //uint64_t querydb_apply_index_update = 0; + // uint64_t querydb_apply_index_update = 0; }; -MAKE_REFLECT_STRUCT(PerformanceImportFile, index_parse, index_build, querydb_id_map, index_save_to_disk, index_load_cached, index_make_delta); \ No newline at end of file +MAKE_REFLECT_STRUCT(PerformanceImportFile, + index_parse, + index_build, + querydb_id_map, + index_save_to_disk, + index_load_cached, + index_make_delta); \ No newline at end of file diff --git a/src/platform.cc b/src/platform.cc index ae7a5f74..15cd8e56 100644 --- a/src/platform.cc +++ b/src/platform.cc @@ -2,18 +2,19 @@ #include #include -#include #include +#include #include #include + #include namespace { // See http://stackoverflow.com/a/236803 -template -void Split(const std::string &s, char delim, Out result) { +template +void Split(const std::string& s, char delim, Out result) { std::stringstream ss; ss.str(s); std::string item; @@ -22,7 +23,7 @@ void Split(const std::string &s, char delim, Out result) { *(result++) = item; } } -std::vector Split(const std::string &s, char delim) { +std::vector Split(const std::string& s, char delim) { std::vector elems; Split(s, delim, std::back_inserter(elems)); return elems; @@ -70,14 +71,16 @@ void MakeDirectoryRecursive(std::string path) { } if (first_success == -1) { - std::cerr << "Failed to make any parent directory for " << path << std::endl; + std::cerr << "Failed to make any parent directory for " << path + << std::endl; exit(1); } // Make all child directories. for (int i = first_success + 1; i <= components.size(); ++i) { if (TryMakeDirectory(prefix + Join(components, '/', i)) == false) { - std::cerr << "Failed making directory for " << path << " even after creating parent directories" << std::endl; + std::cerr << "Failed making directory for " << path + << " even after creating parent directories" << std::endl; exit(1); } } diff --git a/src/platform.h b/src/platform.h index 999fdf6e..0df07d25 100644 --- a/src/platform.h +++ b/src/platform.h @@ -6,8 +6,8 @@ #include #include -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; struct PlatformMutex { virtual ~PlatformMutex(); diff --git a/src/platform_linux.cc b/src/platform_linux.cc index 9ac4374b..5ffc48a4 100644 --- a/src/platform_linux.cc +++ b/src/platform_linux.cc @@ -6,34 +6,39 @@ #include #include -#include -#include #include +#include #include +#include + -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include #include +#include +#include +#include +#include +#include + #include -#include // required for stat.h #include +#include // required for stat.h + +#include #include #include -#include -#include /* For O_* constants */ -#include /* For mode constants */ + +#include /* For O_* constants */ #include #include +#include /* For mode constants */ + #ifndef __APPLE__ #include @@ -85,8 +90,9 @@ struct PlatformSharedMemoryLinux : public PlatformSharedMemory { int fd_; PlatformSharedMemoryLinux(const std::string& name, size_t size) - : name_(name), size_(size) { - std::cerr << "PlatformSharedMemoryLinux name=" << name << ", size=" << size << std::endl; + : name_(name), size_(size) { + std::cerr << "PlatformSharedMemoryLinux name=" << name << ", size=" << size + << std::endl; // Try to create shared memory but only if it does not already exist. Since // we created the memory, we need to initialize it. @@ -105,9 +111,8 @@ struct PlatformSharedMemoryLinux : public PlatformSharedMemory { } // Map the shared memory to an address. - data = - CHECKED(mmap(nullptr /*kernel assigned starting address*/, size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0 /*offset*/)); + data = CHECKED(mmap(nullptr /*kernel assigned starting address*/, size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0 /*offset*/)); capacity = size; std::cerr << "Open shared memory name=" << name << ", fd=" << fd_ @@ -134,13 +139,13 @@ std::unique_ptr CreatePlatformScopedMutexLock( } std::unique_ptr CreatePlatformSharedMemory( - const std::string& name, size_t size) { + const std::string& name, + size_t size) { std::string name2 = "/" + name; return MakeUnique(name2, size); } -void PlatformInit() { -} +void PlatformInit() {} std::string NormalizePath(const std::string& path) { errno = 0; @@ -152,7 +157,7 @@ std::string NormalizePath(const std::string& path) { } bool TryMakeDirectory(const std::string& absolute_path) { - const mode_t kMode = 0777; // UNIX style permissions + const mode_t kMode = 0777; // UNIX style permissions if (mkdir(absolute_path.c_str(), kMode) == -1) { // Success if the directory exists. return errno == EEXIST; @@ -172,14 +177,16 @@ optional GetLastModificationTime(const std::string& absolute_path) { if (stat(absolute_path.c_str(), &buf) != 0) { switch (errno) { case ENOENT: - //std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl; + // std::cerr << "GetLastModificationTime: unable to find file " << + // absolute_path << std::endl; return nullopt; case EINVAL: - //std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl; + // std::cerr << "GetLastModificationTime: invalid param to _stat for + // file file " << absolute_path << std::endl; return nullopt; default: - //std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl; - //exit(1); + // std::cerr << "GetLastModificationTime: unhandled for " << + // absolute_path << std::endl; exit(1); return nullopt; } } @@ -205,7 +212,7 @@ void CopyFileTo(const std::string& dest, const std::string& source) { char buf[4096]; ssize_t nread; while (nread = read(fd_from, buf, sizeof buf), nread > 0) { - char *out_ptr = buf; + char* out_ptr = buf; ssize_t nwritten; do { @@ -214,8 +221,7 @@ void CopyFileTo(const std::string& dest, const std::string& source) { if (nwritten >= 0) { nread -= nwritten; out_ptr += nwritten; - } - else if (errno != EINTR) + } else if (errno != EINTR) goto out_error; } while (nread > 0); } diff --git a/src/platform_win.cc b/src/platform_win.cc index e3e4f991..ad44aaca 100644 --- a/src/platform_win.cc +++ b/src/platform_win.cc @@ -5,13 +5,15 @@ #include +#include #include #include #include -#include -#include + #include +#include + #include #include @@ -23,21 +25,21 @@ namespace { DWORD CheckForError(std::vector allow) { DWORD error = GetLastError(); if (error == ERROR_SUCCESS || - std::find(allow.begin(), allow.end(), error) != allow.end()) + std::find(allow.begin(), allow.end(), error) != allow.end()) return error; // See http://stackoverflow.com/a/17387176 LPSTR message_buffer = nullptr; size_t size = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&message_buffer, 0, NULL); + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&message_buffer, 0, NULL); std::string message(message_buffer, size); LocalFree(message_buffer); std::cerr << "Windows error code=" << error << ", message=" << message - << std::endl; + << std::endl; assert(false); // debugger break exit(1); @@ -49,7 +51,7 @@ struct PlatformMutexWin : public PlatformMutex { PlatformMutexWin(const std::string& name) { std::cerr << "[win] Creating mutex with name " << name << std::endl; raw_mutex = CreateMutex(nullptr, false /*initial_owner*/, name.c_str()); - CheckForError({ ERROR_ALREADY_EXISTS }); + CheckForError({ERROR_ALREADY_EXISTS}); } ~PlatformMutexWin() override { @@ -65,12 +67,12 @@ struct PlatformScopedMutexLockWin : public PlatformScopedMutexLock { PlatformScopedMutexLockWin(HANDLE raw_mutex) : raw_mutex(raw_mutex) { DWORD result = WaitForSingleObject(raw_mutex, INFINITE); assert(result == WAIT_OBJECT_0); - CheckForError({ ERROR_NO_MORE_FILES, ERROR_ALREADY_EXISTS } /*allow*/); + CheckForError({ERROR_NO_MORE_FILES, ERROR_ALREADY_EXISTS} /*allow*/); } ~PlatformScopedMutexLockWin() override { ReleaseMutex(raw_mutex); - CheckForError({ ERROR_NO_MORE_FILES, ERROR_ALREADY_EXISTS } /*allow*/); + CheckForError({ERROR_NO_MORE_FILES, ERROR_ALREADY_EXISTS} /*allow*/); } }; @@ -79,15 +81,15 @@ struct PlatformSharedMemoryWin : public PlatformSharedMemory { PlatformSharedMemoryWin(const std::string& name, size_t capacity) { std::cerr << "[win] Creating shared memory with name " << name - << " and capacity " << capacity << std::endl; + << " and capacity " << capacity << std::endl; this->name = name; shmem_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, - (DWORD)capacity, name.c_str()); - CheckForError({ ERROR_ALREADY_EXISTS } /*allow*/); + (DWORD)capacity, name.c_str()); + CheckForError({ERROR_ALREADY_EXISTS} /*allow*/); data = MapViewOfFile(shmem_, FILE_MAP_ALL_ACCESS, 0, 0, capacity); - CheckForError({ ERROR_ALREADY_EXISTS } /*allow*/); + CheckForError({ERROR_ALREADY_EXISTS} /*allow*/); this->capacity = capacity; } @@ -108,14 +110,14 @@ std::unique_ptr CreatePlatformMutex(const std::string& name) { } std::unique_ptr CreatePlatformScopedMutexLock( - PlatformMutex* mutex) { + PlatformMutex* mutex) { return MakeUnique( - static_cast(mutex)->raw_mutex); + static_cast(mutex)->raw_mutex); } std::unique_ptr CreatePlatformSharedMemory( - const std::string& name, - size_t size) { + const std::string& name, + size_t size) { return MakeUnique(name, size); } @@ -137,7 +139,7 @@ std::string NormalizePath(const std::string& path) { DWORD retval = 0; TCHAR buffer[MAX_PATH] = TEXT(""); TCHAR buf[MAX_PATH] = TEXT(""); - TCHAR** lpp_part = { NULL }; + TCHAR** lpp_part = {NULL}; retval = GetFullPathName(path.c_str(), MAX_PATH, buffer, lpp_part); // fail, return original @@ -146,7 +148,7 @@ std::string NormalizePath(const std::string& path) { std::string result = buffer; std::replace(result.begin(), result.end(), '\\', '/'); - //std::transform(result.begin(), result.end(), result.begin(), ::tolower); + // std::transform(result.begin(), result.end(), result.begin(), ::tolower); return result; } @@ -160,13 +162,12 @@ bool TryMakeDirectory(const std::string& absolute_path) { // See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx const DWORD MS_VC_EXCEPTION = 0x406D1388; -#pragma pack(push,8) -typedef struct tagTHREADNAME_INFO -{ - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. +#pragma pack(push, 8) +typedef struct tagTHREADNAME_INFO { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) void SetCurrentThreadName(const std::string& thread_name) { @@ -179,9 +180,10 @@ void SetCurrentThreadName(const std::string& thread_name) { info.dwFlags = 0; __try { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), + (ULONG_PTR*)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { } - __except (EXCEPTION_EXECUTE_HANDLER) {} } optional GetLastModificationTime(const std::string& absolute_path) { @@ -189,14 +191,16 @@ optional GetLastModificationTime(const std::string& absolute_path) { if (_stat(absolute_path.c_str(), &buf) != 0) { switch (errno) { case ENOENT: - //std::cerr << "GetLastModificationTime: unable to find file " << absolute_path << std::endl; + // std::cerr << "GetLastModificationTime: unable to find file " << + // absolute_path << std::endl; return nullopt; case EINVAL: - //std::cerr << "GetLastModificationTime: invalid param to _stat for file file " << absolute_path << std::endl; + // std::cerr << "GetLastModificationTime: invalid param to _stat for + // file file " << absolute_path << std::endl; return nullopt; default: - //std::cerr << "GetLastModificationTime: unhandled for " << absolute_path << std::endl; - //exit(1); + // std::cerr << "GetLastModificationTime: unhandled for " << + // absolute_path << std::endl; exit(1); return nullopt; } } @@ -205,15 +209,11 @@ optional GetLastModificationTime(const std::string& absolute_path) { } void MoveFileTo(const std::string& destination, const std::string& source) { - MoveFile(source.c_str(), - destination.c_str()); + MoveFile(source.c_str(), destination.c_str()); } void CopyFileTo(const std::string& destination, const std::string& source) { - CopyFile( - source.c_str(), - destination.c_str(), - false /*failIfExists*/); + CopyFile(source.c_str(), destination.c_str(), false /*failIfExists*/); } bool IsSymLink(const std::string& path) { @@ -221,10 +221,7 @@ bool IsSymLink(const std::string& path) { } std::vector GetPlatformClangArguments() { - return { - "-fms-compatibility", - "-fdelayed-template-parsing" - }; + return {"-fms-compatibility", "-fdelayed-template-parsing"}; } void FreeUnusedMemory() {} diff --git a/src/position.cc b/src/position.cc index 0cfc191f..32c9e87f 100644 --- a/src/position.cc +++ b/src/position.cc @@ -12,8 +12,7 @@ const char* SkipAfter(const char* input, char skip_after) { Position::Position() {} -Position::Position(int16_t line, int16_t column) - : line(line), column(column) {} +Position::Position(int16_t line, int16_t column) : line(line), column(column) {} Position::Position(const char* encoded) { assert(encoded); @@ -61,7 +60,9 @@ bool Position::operator==(const Position& that) const { return line == that.line && column == that.column; } -bool Position::operator!=(const Position& that) const { return !(*this == that); } +bool Position::operator!=(const Position& that) const { + return !(*this == that); +} bool Position::operator<(const Position& that) const { if (line < that.line) @@ -133,7 +134,9 @@ bool Range::operator==(const Range& that) const { return start == that.start && end == that.end; } -bool Range::operator!=(const Range& that) const { return !(*this == that); } +bool Range::operator!=(const Range& that) const { + return !(*this == that); +} bool Range::operator<(const Range& that) const { if (start < that.start) @@ -150,7 +153,6 @@ void Reflect(Writer& visitor, Position& value) { visitor.String(output.c_str(), (rapidjson::SizeType)output.size()); } - // Range void Reflect(Reader& visitor, Range& value) { value = Range(visitor.GetString()); diff --git a/src/position.h b/src/position.h index 3e02900f..205bb8ed 100644 --- a/src/position.h +++ b/src/position.h @@ -24,7 +24,9 @@ struct Position { bool operator!=(const Position& that) const; bool operator<(const Position& that) const; }; -static_assert(sizeof(Position) == 4, "Investigate, Position should be 32-bits for indexer size reasons"); +static_assert( + sizeof(Position) == 4, + "Investigate, Position should be 32-bits for indexer size reasons"); MAKE_HASHABLE(Position, t.line, t.column); struct Range { diff --git a/src/project.cc b/src/project.cc index 67e8d7d0..f0d41863 100644 --- a/src/project.cc +++ b/src/project.cc @@ -1,11 +1,12 @@ #include "project.h" -#include "match.h" #include "libclangmm/Utility.h" +#include "match.h" #include "platform.h" #include "serializer.h" #include "utils.h" + #include #include #include @@ -26,79 +27,40 @@ MAKE_REFLECT_STRUCT(CompileCommandsEntry, directory, file, command, args); namespace { - -static const char* kBlacklistMulti[] = { - "-MF", - "-Xclang" -}; +static const char* kBlacklistMulti[] = {"-MF", "-Xclang"}; // Blacklisted flags which are always removed from the command line. -static const char *kBlacklist[] = { - "--param", - "-M", - "-MD", - "-MG", - "-MM", - "-MMD", - "-MP", - "-MQ", - "-MT", - "-Og", - "-Wa,--32", - "-Wa,--64", - "-Wl,--incremental-full", - "-Wl,--incremental-patch,1", - "-Wl,--no-incremental", - "-fbuild-session-file=", - "-fbuild-session-timestamp=", - "-fembed-bitcode", - "-fembed-bitcode-marker", - "-fmodules-validate-once-per-build-session", - "-fno-delete-null-pointer-checks", - "-fno-use-linker-plugin" - "-fno-var-tracking", - "-fno-var-tracking-assignments", - "-fno-enforce-eh-specs", - "-fvar-tracking", - "-fvar-tracking-assignments", - "-fvar-tracking-assignments-toggle", - "-gcc-toolchain", - "-march=", - "-masm=", - "-mcpu=", - "-mfpmath=", - "-mtune=", - "-s", +static const char* kBlacklist[] = { + "--param", "-M", "-MD", "-MG", "-MM", "-MMD", "-MP", "-MQ", "-MT", "-Og", + "-Wa,--32", "-Wa,--64", "-Wl,--incremental-full", + "-Wl,--incremental-patch,1", "-Wl,--no-incremental", + "-fbuild-session-file=", "-fbuild-session-timestamp=", "-fembed-bitcode", + "-fembed-bitcode-marker", "-fmodules-validate-once-per-build-session", + "-fno-delete-null-pointer-checks", + "-fno-use-linker-plugin" + "-fno-var-tracking", + "-fno-var-tracking-assignments", "-fno-enforce-eh-specs", "-fvar-tracking", + "-fvar-tracking-assignments", "-fvar-tracking-assignments-toggle", + "-gcc-toolchain", + "-march=", "-masm=", "-mcpu=", "-mfpmath=", "-mtune=", "-s", - "-B", - //"-f", - //"-pipe", - //"-W", - // TODO: make sure we consume includes before stripping all path-like args. - "/work/goma/gomacc", - "../../third_party/llvm-build/Release+Asserts/bin/clang++", - "-Wno-unused-lambda-capture", - "/", - "..", - //"-stdlib=libc++" + "-B", + //"-f", + //"-pipe", + //"-W", + // TODO: make sure we consume includes before stripping all path-like args. + "/work/goma/gomacc", + "../../third_party/llvm-build/Release+Asserts/bin/clang++", + "-Wno-unused-lambda-capture", "/", "..", + //"-stdlib=libc++" }; // Arguments which are followed by a potentially relative path. We need to make // all relative paths absolute, otherwise libclang will not resolve them. -const char* kPathArgs[] = { - "-I", - "-iquote", - "-isystem", - "--sysroot=" -}; +const char* kPathArgs[] = {"-I", "-iquote", "-isystem", "--sysroot="}; -const char* kQuoteIncludeArgs[] = { - "-iquote" -}; -const char* kAngleIncludeArgs[] = { - "-I", - "-isystem" -}; +const char* kQuoteIncludeArgs[] = {"-iquote"}; +const char* kAngleIncludeArgs[] = {"-I", "-isystem"}; bool ShouldAddToQuoteIncludes(const std::string& arg) { for (const char* flag_type : kQuoteIncludeArgs) { @@ -122,8 +84,10 @@ bool IsCFile(const std::string& path) { } Project::Entry GetCompilationEntryFromCompileCommandEntry( - std::unordered_set& quote_includes, std::unordered_set& angle_includes, - const std::vector& extra_flags, const CompileCommandsEntry& entry) { + std::unordered_set& quote_includes, + std::unordered_set& angle_includes, + const std::vector& extra_flags, + const CompileCommandsEntry& entry) { Project::Entry result; result.filename = NormalizePath(entry.file); @@ -136,15 +100,15 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( std::string arg = entry.args[i]; // If blacklist skip. - if (std::any_of(std::begin(kBlacklistMulti), std::end(kBlacklistMulti), [&arg](const char* value) { - return StartsWith(arg, value); - })) { + if (std::any_of( + std::begin(kBlacklistMulti), std::end(kBlacklistMulti), + [&arg](const char* value) { return StartsWith(arg, value); })) { ++i; continue; } - if (std::any_of(std::begin(kBlacklist), std::end(kBlacklist), [&arg](const char* value) { - return StartsWith(arg, value); - })) { + if (std::any_of( + std::begin(kBlacklist), std::end(kBlacklist), + [&arg](const char* value) { return StartsWith(arg, value); })) { continue; } @@ -153,7 +117,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( if (arg.size() > 0 && arg[0] != '/') arg = NormalizePath(entry.directory + arg); make_next_flag_absolute = false; - + if (add_next_flag_quote) quote_includes.insert(arg); if (add_next_flag_angle) @@ -215,12 +179,12 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry( /* TODO: Fix this function, it may be way faster than libclang's implementation. std::vector LoadFromCompileCommandsJson( - std::unordered_set& quote_includes, std::unordered_set& angle_includes, - const std::vector& extra_flags, const std::string& project_directory) { + std::unordered_set& quote_includes, +std::unordered_set& angle_includes, const std::vector& +extra_flags, const std::string& project_directory) { - optional compile_commands_content = ReadContent(project_directory + "/compile_commands.json"); - if (!compile_commands_content) - return {}; + optional compile_commands_content = ReadContent(project_directory ++ "/compile_commands.json"); if (!compile_commands_content) return {}; rapidjson::Document reader; reader.Parse(compile_commands_content->c_str()); @@ -236,15 +200,18 @@ std::vector LoadFromCompileCommandsJson( if (entry.args.empty() && !entry.command.empty()) entry.args = SplitString(entry.command, " "); - result.push_back(GetCompilationEntryFromCompileCommandEntry(quote_includes, angle_includes, extra_flags, entry)); + result.push_back(GetCompilationEntryFromCompileCommandEntry(quote_includes, +angle_includes, extra_flags, entry)); } return result; } */ std::vector LoadFromDirectoryListing( - std::unordered_set& quote_includes, std::unordered_set& angle_includes, - const std::vector& extra_flags, const std::string& project_directory) { + std::unordered_set& quote_includes, + std::unordered_set& angle_includes, + const std::vector& extra_flags, + const std::string& project_directory) { std::vector result; std::vector args; @@ -259,14 +226,16 @@ std::vector LoadFromDirectoryListing( } std::cerr << std::endl; - - std::vector files = GetFilesInFolder(project_directory, true /*recursive*/, true /*add_folder_to_path*/); + std::vector files = GetFilesInFolder( + project_directory, true /*recursive*/, true /*add_folder_to_path*/); for (const std::string& file : files) { - if (EndsWith(file, ".cc") || EndsWith(file, ".cpp") || EndsWith(file, ".c")) { + if (EndsWith(file, ".cc") || EndsWith(file, ".cpp") || + EndsWith(file, ".c")) { CompileCommandsEntry e; e.file = NormalizePath(file); e.args = args; - result.push_back(GetCompilationEntryFromCompileCommandEntry(quote_includes, angle_includes, extra_flags, e)); + result.push_back(GetCompilationEntryFromCompileCommandEntry( + quote_includes, angle_includes, extra_flags, e)); } } @@ -274,28 +243,38 @@ std::vector LoadFromDirectoryListing( } std::vector LoadCompilationEntriesFromDirectory( - std::unordered_set& quote_includes, std::unordered_set& angle_includes, - const std::vector& extra_flags, const std::string& project_directory) { + std::unordered_set& quote_includes, + std::unordered_set& angle_includes, + const std::vector& extra_flags, + const std::string& project_directory) { // TODO: Figure out if this function or the clang one is faster. - //return LoadFromCompileCommandsJson(extra_flags, project_directory); + // return LoadFromCompileCommandsJson(extra_flags, project_directory); std::cerr << "Trying to load compile_commands.json" << std::endl; CXCompilationDatabase_Error cx_db_load_error; - CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory(project_directory.c_str(), &cx_db_load_error); + CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory( + project_directory.c_str(), &cx_db_load_error); if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) { - std::cerr << "Unable to load compile_commands.json located at \"" << project_directory << "\"; using directory listing instead." << std::endl; - return LoadFromDirectoryListing(quote_includes, angle_includes, extra_flags, project_directory); + std::cerr << "Unable to load compile_commands.json located at \"" + << project_directory << "\"; using directory listing instead." + << std::endl; + return LoadFromDirectoryListing(quote_includes, angle_includes, extra_flags, + project_directory); } - CXCompileCommands cx_commands = clang_CompilationDatabase_getAllCompileCommands(cx_db); + CXCompileCommands cx_commands = + clang_CompilationDatabase_getAllCompileCommands(cx_db); unsigned int num_commands = clang_CompileCommands_getSize(cx_commands); std::vector result; for (unsigned int i = 0; i < num_commands; i++) { - CXCompileCommand cx_command = clang_CompileCommands_getCommand(cx_commands, i); + CXCompileCommand cx_command = + clang_CompileCommands_getCommand(cx_commands, i); - std::string directory = clang::ToString(clang_CompileCommand_getDirectory(cx_command)); - std::string relative_filename = clang::ToString(clang_CompileCommand_getFilename(cx_command)); + std::string directory = + clang::ToString(clang_CompileCommand_getDirectory(cx_command)); + std::string relative_filename = + clang::ToString(clang_CompileCommand_getFilename(cx_command)); std::string absolute_filename = directory + "/" + relative_filename; CompileCommandsEntry entry; @@ -305,9 +284,11 @@ std::vector LoadCompilationEntriesFromDirectory( unsigned num_args = clang_CompileCommand_getNumArgs(cx_command); entry.args.reserve(num_args); for (unsigned j = 0; j < num_args; ++j) - entry.args.push_back(clang::ToString(clang_CompileCommand_getArg(cx_command, j))); + entry.args.push_back( + clang::ToString(clang_CompileCommand_getArg(cx_command, j))); - result.push_back(GetCompilationEntryFromCompileCommandEntry(quote_includes, angle_includes, extra_flags, entry)); + result.push_back(GetCompilationEntryFromCompileCommandEntry( + quote_includes, angle_includes, extra_flags, entry)); } clang_CompileCommands_dispose(cx_commands); @@ -356,14 +337,18 @@ int ComputeGuessScore(const std::string& a, const std::string& b) { } // namespace -void Project::Load(const std::vector& extra_flags, const std::string& directory) { +void Project::Load(const std::vector& extra_flags, + const std::string& directory) { std::unordered_set unique_quote_includes; std::unordered_set unique_angle_includes; - entries = LoadCompilationEntriesFromDirectory(unique_quote_includes, unique_angle_includes, extra_flags, directory); + entries = LoadCompilationEntriesFromDirectory( + unique_quote_includes, unique_angle_includes, extra_flags, directory); - quote_include_directories.assign(unique_quote_includes.begin(), unique_quote_includes.end()); - angle_include_directories.assign(unique_angle_includes.begin(), unique_angle_includes.end()); + quote_include_directories.assign(unique_quote_includes.begin(), + unique_quote_includes.end()); + angle_include_directories.assign(unique_angle_includes.begin(), + unique_angle_includes.end()); for (std::string& path : quote_include_directories) { EnsureEndsInSlash(path); @@ -379,7 +364,8 @@ void Project::Load(const std::vector& extra_flags, const std::strin absolute_path_to_entry_index_[entries[i].filename] = i; } -Project::Entry Project::FindCompilationEntryForFile(const std::string& filename) { +Project::Entry Project::FindCompilationEntryForFile( + const std::string& filename) { auto it = absolute_path_to_entry_index_.find(filename); if (it != absolute_path_to_entry_index_.end()) return entries[it->second]; @@ -404,7 +390,9 @@ Project::Entry Project::FindCompilationEntryForFile(const std::string& filename) return result; } -void Project::ForAllFilteredFiles(Config* config, std::function action) { +void Project::ForAllFilteredFiles( + Config* config, + std::function action) { GroupMatch matcher(config->indexWhitelist, config->indexBlacklist); for (int i = 0; i < entries.size(); ++i) { const Project::Entry& entry = entries[i]; @@ -413,7 +401,8 @@ void Project::ForAllFilteredFiles(Config* config, std::functionlogSkippedPathsForIndex) { - LOG_S(INFO) << "[" << i + 1 << "/" << entries.size() << "]: Failed " << failure_reason << "; skipping " << entry.filename; + LOG_S(INFO) << "[" << i + 1 << "/" << entries.size() << "]: Failed " + << failure_reason << "; skipping " << entry.filename; } } } @@ -425,36 +414,39 @@ TEST_CASE("Entry inference") { Project p; { Project::Entry e; - e.args = { "arg1" }; + e.args = {"arg1"}; e.filename = "/a/b/c/d/bar.cc"; p.entries.push_back(e); } { Project::Entry e; - e.args = { "arg2" }; + e.args = {"arg2"}; e.filename = "/a/b/c/baz.cc"; p.entries.push_back(e); } // Guess at same directory level, when there are parent directories. { - optional entry = p.FindCompilationEntryForFile("/a/b/c/d/new.cc"); + optional entry = + p.FindCompilationEntryForFile("/a/b/c/d/new.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg1" }); + REQUIRE(entry->args == std::vector{"arg1"}); } // Guess at same directory level, when there are child directories. { - optional entry = p.FindCompilationEntryForFile("/a/b/c/new.cc"); + optional entry = + p.FindCompilationEntryForFile("/a/b/c/new.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg2" }); + REQUIRE(entry->args == std::vector{"arg2"}); } // Guess at new directory (use the closest parent directory). { - optional entry = p.FindCompilationEntryForFile("/a/b/c/new/new.cc"); + optional entry = + p.FindCompilationEntryForFile("/a/b/c/new/new.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg2" }); + REQUIRE(entry->args == std::vector{"arg2"}); } } @@ -462,51 +454,55 @@ TEST_CASE("Entry inference prefers same file endings") { Project p; { Project::Entry e; - e.args = { "arg1" }; + e.args = {"arg1"}; e.filename = "common/simple_browsertest.cc"; p.entries.push_back(e); } { Project::Entry e; - e.args = { "arg2" }; + e.args = {"arg2"}; e.filename = "common/simple_unittest.cc"; p.entries.push_back(e); } { Project::Entry e; - e.args = { "arg3" }; + e.args = {"arg3"}; e.filename = "common/a/simple_unittest.cc"; p.entries.push_back(e); } - // Prefer files with the same ending. { - optional entry = p.FindCompilationEntryForFile("my_browsertest.cc"); + optional entry = + p.FindCompilationEntryForFile("my_browsertest.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg1" }); + REQUIRE(entry->args == std::vector{"arg1"}); } { - optional entry = p.FindCompilationEntryForFile("my_unittest.cc"); + optional entry = + p.FindCompilationEntryForFile("my_unittest.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg2" }); + REQUIRE(entry->args == std::vector{"arg2"}); } { - optional entry = p.FindCompilationEntryForFile("common/my_browsertest.cc"); + optional entry = + p.FindCompilationEntryForFile("common/my_browsertest.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg1" }); + REQUIRE(entry->args == std::vector{"arg1"}); } { - optional entry = p.FindCompilationEntryForFile("common/my_unittest.cc"); + optional entry = + p.FindCompilationEntryForFile("common/my_unittest.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg2" }); + REQUIRE(entry->args == std::vector{"arg2"}); } // Prefer the same directory over matching file-ending. { - optional entry = p.FindCompilationEntryForFile("common/a/foo.cc"); + optional entry = + p.FindCompilationEntryForFile("common/a/foo.cc"); REQUIRE(entry.has_value()); - REQUIRE(entry->args == std::vector{ "arg3" }); + REQUIRE(entry->args == std::vector{"arg3"}); } } diff --git a/src/project.h b/src/project.h index 3d89f724..3282051c 100644 --- a/src/project.h +++ b/src/project.h @@ -10,8 +10,8 @@ #include #include -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; struct Project { struct Entry { @@ -35,12 +35,14 @@ struct Project { // discover all files and args. Otherwise, a recursive directory listing of // all *.cpp, *.cc, *.h, and *.hpp files will be used. clang arguments can be // specified in a clang_args file located inside of |directory|. - void Load(const std::vector& extra_flags, const std::string& directory); + void Load(const std::vector& extra_flags, + const std::string& directory); // Lookup the CompilationEntry for |filename|. If no entry was found this // will infer one based on existing project structure. Entry FindCompilationEntryForFile(const std::string& filename); - void ForAllFilteredFiles(Config* config, std::function action); + void ForAllFilteredFiles( + Config* config, + std::function action); }; - diff --git a/src/query.cc b/src/query.cc index 8246c48f..4bf7ca7f 100644 --- a/src/query.cc +++ b/src/query.cc @@ -2,24 +2,26 @@ #include "indexer.h" -#include #include +#include #include + #include #include #include -#include -#include -#include #include +#include +#include +#include + // TODO: Make all copy constructors explicit. - namespace { -optional ToQuery(const IdMap& id_map, const IndexType::Def& type) { +optional ToQuery(const IdMap& id_map, + const IndexType::Def& type) { if (type.detailed_name.empty()) return nullopt; @@ -36,7 +38,8 @@ optional ToQuery(const IdMap& id_map, const IndexType::Def return result; } -optional ToQuery(const IdMap& id_map, const IndexFunc::Def& func) { +optional ToQuery(const IdMap& id_map, + const IndexFunc::Def& func) { if (func.detailed_name.empty()) return nullopt; @@ -52,7 +55,8 @@ optional ToQuery(const IdMap& id_map, const IndexFunc::Def return result; } -optional ToQuery(const IdMap& id_map, const IndexVar::Def& var) { +optional ToQuery(const IdMap& id_map, + const IndexVar::Def& var) { if (var.detailed_name.empty()) return nullopt; @@ -69,15 +73,13 @@ optional ToQuery(const IdMap& id_map, const IndexVar::Def& return result; } - // Adds the mergeable updates in |source| to |dest|. If a mergeable update for // the destination type already exists, it will be combined. This makes merging // updates take longer but reduces import time on the querydb thread. template void AddMergeableRange( - std::vector>* dest, - const std::vector>& source) { - + std::vector>* dest, + const std::vector>& source) { // TODO: Consider caching the lookup table. It can probably save even more // time at the cost of some additional memory. @@ -93,8 +95,7 @@ void AddMergeableRange( if (it != id_to_index.end()) { AddRange(&(*dest)[it->second].to_add, entry.to_add); AddRange(&(*dest)[it->second].to_remove, entry.to_remove); - } - else { + } else { dest->push_back(entry); } } @@ -105,34 +106,31 @@ void AddMergeableRange( // that are in |current| but not |previous| to |added|. // // Returns true iff |removed| or |added| are non-empty. -template -bool ComputeDifferenceForUpdate( - std::vector& previous, std::vector& current, - std::vector* removed, std::vector* added) { - +template +bool ComputeDifferenceForUpdate(std::vector& previous, + std::vector& current, + std::vector* removed, + std::vector* added) { // We need to sort to use std::set_difference. std::sort(previous.begin(), previous.end()); std::sort(current.begin(), current.end()); // Returns the elements in |previous| that are not in |current|. - std::set_difference( - previous.begin(), previous.end(), - current.begin(), current.end(), - std::back_inserter(*removed)); + std::set_difference(previous.begin(), previous.end(), current.begin(), + current.end(), std::back_inserter(*removed)); // Returns the elements in |current| that are not in |previous|. - std::set_difference( - current.begin(), current.end(), - previous.begin(), previous.end(), - std::back_inserter(*added)); + std::set_difference(current.begin(), current.end(), previous.begin(), + previous.end(), std::back_inserter(*added)); return !removed->empty() || !added->empty(); } -template -void CompareGroups( - std::vector& previous_data, std::vector& current_data, - std::function on_removed, std::function on_added, std::function on_found) { - +template +void CompareGroups(std::vector& previous_data, + std::vector& current_data, + std::function on_removed, + std::function on_added, + std::function on_found) { std::sort(previous_data.begin(), previous_data.end()); std::sort(current_data.begin(), current_data.end()); @@ -186,7 +184,8 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) { for (const IndexType& type : indexed.types) { if (type.def.definition_spelling.has_value()) - add_all_symbols(id_map.ToSymbol(type.id), type.def.definition_spelling.value()); + add_all_symbols(id_map.ToSymbol(type.id), + type.def.definition_spelling.value()); if (type.def.definition_extent.has_value()) add_outline(id_map.ToSymbol(type.id), type.def.definition_extent.value()); for (const Range& use : type.uses) @@ -194,7 +193,8 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) { } for (const IndexFunc& func : indexed.funcs) { if (func.def.definition_spelling.has_value()) - add_all_symbols(id_map.ToSymbol(func.id), func.def.definition_spelling.value()); + add_all_symbols(id_map.ToSymbol(func.id), + func.def.definition_spelling.value()); if (func.def.definition_extent.has_value()) add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value()); for (const IndexFunc::Declaration& decl : func.declarations) { @@ -203,63 +203,37 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) { add_outline(id_map.ToSymbol(func.id), decl.spelling); } for (const IndexFuncRef& caller : func.callers) { - if (caller.is_implicit) continue; + if (caller.is_implicit) + continue; add_all_symbols(id_map.ToSymbol(func.id), caller.loc); } } for (const IndexVar& var : indexed.vars) { if (var.def.definition_spelling.has_value()) - add_all_symbols(id_map.ToSymbol(var.id), var.def.definition_spelling.value()); + add_all_symbols(id_map.ToSymbol(var.id), + var.def.definition_spelling.value()); if (var.def.definition_extent.has_value()) add_outline(id_map.ToSymbol(var.id), var.def.definition_extent.value()); for (const Range& use : var.uses) add_all_symbols(id_map.ToSymbol(var.id), use); } - std::sort(def.outline.begin(), def.outline.end(), [](const SymbolRef& a, const SymbolRef& b) { - return a.loc.range.start < b.loc.range.start; - }); - std::sort(def.all_symbols.begin(), def.all_symbols.end(), [](const SymbolRef& a, const SymbolRef& b) { - return a.loc.range.start < b.loc.range.start; - }); + std::sort(def.outline.begin(), def.outline.end(), + [](const SymbolRef& a, const SymbolRef& b) { + return a.loc.range.start < b.loc.range.start; + }); + std::sort(def.all_symbols.begin(), def.all_symbols.end(), + [](const SymbolRef& a, const SymbolRef& b) { + return a.loc.range.start < b.loc.range.start; + }); return def; } } // namespace - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -QueryFileId GetQueryFileIdFromPath(QueryDatabase* query_db, const std::string& path) { +QueryFileId GetQueryFileIdFromPath(QueryDatabase* query_db, + const std::string& path) { auto it = query_db->usr_to_file.find(LowerPathIfCaseInsensitive(path)); if (it != query_db->usr_to_file.end()) return QueryFileId(it->second.id); @@ -304,17 +278,19 @@ QueryVarId GetQueryVarIdFromUsr(QueryDatabase* query_db, const Usr& usr) { } IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids) - : local_ids(local_ids) { - //LOG_S(INFO) << "Creating IdMap for " << local_ids.primary_file; + : local_ids(local_ids) { + // LOG_S(INFO) << "Creating IdMap for " << local_ids.primary_file; primary_file = GetQueryFileIdFromPath(query_db, local_ids.primary_file); cached_type_ids_.resize(local_ids.type_id_to_usr.size()); for (const auto& entry : local_ids.type_id_to_usr) - cached_type_ids_[entry.first] = GetQueryTypeIdFromUsr(query_db, entry.second); + cached_type_ids_[entry.first] = + GetQueryTypeIdFromUsr(query_db, entry.second); cached_func_ids_.resize(local_ids.func_id_to_usr.size()); for (const auto& entry : local_ids.func_id_to_usr) - cached_func_ids_[entry.first] = GetQueryFuncIdFromUsr(query_db, entry.second); + cached_func_ids_[entry.first] = + GetQueryFuncIdFromUsr(query_db, entry.second); cached_var_ids_.resize(local_ids.var_id_to_usr.size()); for (const auto& entry : local_ids.var_id_to_usr) @@ -329,7 +305,8 @@ QueryTypeId IdMap::ToQuery(IndexTypeId id) const { return QueryTypeId(cached_type_ids_.find(id)->second); } QueryFuncId IdMap::ToQuery(IndexFuncId id) const { - if (id.id == -1) return QueryFuncId((size_t)-1); + if (id.id == -1) + return QueryFuncId((size_t)-1); assert(cached_func_ids_.find(id) != cached_func_ids_.end()); return QueryFuncId(cached_func_ids_.find(id)->second); } @@ -370,14 +347,16 @@ optional IdMap::ToQuery(optional ref) const { return nullopt; return ToQuery(ref.value()); } -optional IdMap::ToQuery(optional decl) const { +optional IdMap::ToQuery( + optional decl) const { if (!decl) return nullopt; return ToQuery(decl.value()); } -template -std::vector ToQueryTransform(const IdMap& id_map, const std::vector& input) { +template +std::vector ToQueryTransform(const IdMap& id_map, + const std::vector& input) { std::vector result; result.reserve(input.size()); for (const In& in : input) @@ -399,7 +378,8 @@ std::vector IdMap::ToQuery(std::vector ids) const { std::vector IdMap::ToQuery(std::vector refs) const { return ToQueryTransform(*this, refs); } -std::vector IdMap::ToQuery(std::vector decls) const { +std::vector IdMap::ToQuery( + std::vector decls) const { return ToQueryTransform(*this, decls); } @@ -412,33 +392,16 @@ SymbolIdx IdMap::ToSymbol(IndexFuncId id) const { SymbolIdx IdMap::ToSymbol(IndexVarId id) const { return SymbolIdx(SymbolKind::Var, ToQuery(id).id); } - - - - - - - - - - - - - - - - - - - - // ---------------------- // INDEX THREAD FUNCTIONS // ---------------------- // static -IndexUpdate IndexUpdate::CreateDelta(const IdMap* previous_id_map, const IdMap* current_id_map, IndexFile* previous, IndexFile* current) { +IndexUpdate IndexUpdate::CreateDelta(const IdMap* previous_id_map, + const IdMap* current_id_map, + IndexFile* previous, + IndexFile* current) { // This function runs on an indexer thread. if (!previous_id_map) { @@ -449,25 +412,30 @@ IndexUpdate IndexUpdate::CreateDelta(const IdMap* previous_id_map, const IdMap* return IndexUpdate(*previous_id_map, *current_id_map, *previous, *current); } -IndexUpdate::IndexUpdate(const IdMap& previous_id_map, const IdMap& current_id_map, IndexFile& previous_file, IndexFile& current_file) { - // This function runs on an indexer thread. +IndexUpdate::IndexUpdate(const IdMap& previous_id_map, + const IdMap& current_id_map, + IndexFile& previous_file, + IndexFile& current_file) { +// This function runs on an indexer thread. - // |query_name| is the name of the variable on the query type. - // |index_name| is the name of the variable on the index type. - // |type| is the type of the variable. -#define PROCESS_UPDATE_DIFF(type_id, query_name, index_name, type) \ - { \ - /* Check for changes. */ \ - std::vector removed, added; \ - auto previous = previous_id_map.ToQuery(previous_def->index_name); \ - auto current = current_id_map.ToQuery(current_def->index_name); \ - bool did_add = ComputeDifferenceForUpdate( \ - previous, current, \ - &removed, &added); \ - if (did_add) {\ - /*std::cerr << "Adding mergeable update on " << current_def->def.short_name << " (" << current_def->def.usr << ") for field " << #index_name << std::endl;*/ \ - query_name.push_back(MergeableUpdate(current_id_map.ToQuery(current_def->id), added, removed)); \ - } \ +// |query_name| is the name of the variable on the query type. +// |index_name| is the name of the variable on the index type. +// |type| is the type of the variable. +#define PROCESS_UPDATE_DIFF(type_id, query_name, index_name, type) \ + { \ + /* Check for changes. */ \ + std::vector removed, added; \ + auto previous = previous_id_map.ToQuery(previous_def->index_name); \ + auto current = current_id_map.ToQuery(current_def->index_name); \ + bool did_add = \ + ComputeDifferenceForUpdate(previous, current, &removed, &added); \ + if (did_add) { \ + /*std::cerr << "Adding mergeable update on " << \ + * current_def->def.short_name << " (" << current_def->def.usr << ") for \ + * field " << #index_name << std::endl;*/ \ + query_name.push_back(MergeableUpdate( \ + current_id_map.ToQuery(current_def->id), added, removed)); \ + } \ } // File files_def_update.push_back(BuildFileDef(current_id_map, current_file)); @@ -478,115 +446,171 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map, const IdMap& current_id_m // away we don't want to remove the type/func/var usage. // Types - CompareGroups(previous_file.types, current_file.types, - /*onRemoved:*/[this, &previous_id_map](IndexType* type) { - if (type->def.definition_spelling) - types_removed.push_back(type->def.usr); - else { - if (!type->derived.empty()) - types_derived.push_back(QueryType::DerivedUpdate(previous_id_map.ToQuery(type->id), {}, previous_id_map.ToQuery(type->derived))); - if (!type->instances.empty()) - types_instances.push_back(QueryType::InstancesUpdate(previous_id_map.ToQuery(type->id), {}, previous_id_map.ToQuery(type->instances))); - if (!type->uses.empty()) - types_uses.push_back(QueryType::UsesUpdate(previous_id_map.ToQuery(type->id), {}, previous_id_map.ToQuery(type->uses))); - } - }, - /*onAdded:*/[this, ¤t_id_map](IndexType* type) { - optional def_update = ToQuery(current_id_map, type->def); - if (def_update) - types_def_update.push_back(*def_update); - if (!type->derived.empty()) - types_derived.push_back(QueryType::DerivedUpdate(current_id_map.ToQuery(type->id), current_id_map.ToQuery(type->derived))); - if (!type->instances.empty()) - types_instances.push_back(QueryType::InstancesUpdate(current_id_map.ToQuery(type->id), current_id_map.ToQuery(type->instances))); - if (!type->uses.empty()) - types_uses.push_back(QueryType::UsesUpdate(current_id_map.ToQuery(type->id), current_id_map.ToQuery(type->uses))); - }, - /*onFound:*/[this, &previous_id_map, ¤t_id_map](IndexType* previous_def, IndexType* current_def) { - optional previous_remapped_def = ToQuery(previous_id_map, previous_def->def); - optional current_remapped_def = ToQuery(current_id_map, current_def->def); - if (current_remapped_def && previous_remapped_def != current_remapped_def && !current_remapped_def->detailed_name.empty()) - types_def_update.push_back(*current_remapped_def); + CompareGroups( + previous_file.types, current_file.types, + /*onRemoved:*/ + [this, &previous_id_map](IndexType* type) { + if (type->def.definition_spelling) + types_removed.push_back(type->def.usr); + else { + if (!type->derived.empty()) + types_derived.push_back(QueryType::DerivedUpdate( + previous_id_map.ToQuery(type->id), {}, + previous_id_map.ToQuery(type->derived))); + if (!type->instances.empty()) + types_instances.push_back(QueryType::InstancesUpdate( + previous_id_map.ToQuery(type->id), {}, + previous_id_map.ToQuery(type->instances))); + if (!type->uses.empty()) + types_uses.push_back( + QueryType::UsesUpdate(previous_id_map.ToQuery(type->id), {}, + previous_id_map.ToQuery(type->uses))); + } + }, + /*onAdded:*/ + [this, ¤t_id_map](IndexType* type) { + optional def_update = + ToQuery(current_id_map, type->def); + if (def_update) + types_def_update.push_back(*def_update); + if (!type->derived.empty()) + types_derived.push_back( + QueryType::DerivedUpdate(current_id_map.ToQuery(type->id), + current_id_map.ToQuery(type->derived))); + if (!type->instances.empty()) + types_instances.push_back(QueryType::InstancesUpdate( + current_id_map.ToQuery(type->id), + current_id_map.ToQuery(type->instances))); + if (!type->uses.empty()) + types_uses.push_back( + QueryType::UsesUpdate(current_id_map.ToQuery(type->id), + current_id_map.ToQuery(type->uses))); + }, + /*onFound:*/ + [this, &previous_id_map, ¤t_id_map](IndexType* previous_def, + IndexType* current_def) { + optional previous_remapped_def = + ToQuery(previous_id_map, previous_def->def); + optional current_remapped_def = + ToQuery(current_id_map, current_def->def); + if (current_remapped_def && + previous_remapped_def != current_remapped_def && + !current_remapped_def->detailed_name.empty()) + types_def_update.push_back(*current_remapped_def); - PROCESS_UPDATE_DIFF(QueryTypeId, types_derived, derived, QueryTypeId); - PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances, QueryVarId); - PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, QueryLocation); - }); + PROCESS_UPDATE_DIFF(QueryTypeId, types_derived, derived, QueryTypeId); + PROCESS_UPDATE_DIFF(QueryTypeId, types_instances, instances, + QueryVarId); + PROCESS_UPDATE_DIFF(QueryTypeId, types_uses, uses, QueryLocation); + }); // Functions - CompareGroups(previous_file.funcs, current_file.funcs, - /*onRemoved:*/[this, &previous_id_map](IndexFunc* func) { - if (func->def.definition_spelling) { - funcs_removed.push_back(func->def.usr); - } - else { - if (!func->declarations.empty()) - funcs_declarations.push_back(QueryFunc::DeclarationsUpdate(previous_id_map.ToQuery(func->id), {}, previous_id_map.ToQuery(func->declarations))); - if (!func->derived.empty()) - funcs_derived.push_back(QueryFunc::DerivedUpdate(previous_id_map.ToQuery(func->id), {}, previous_id_map.ToQuery(func->derived))); - if (!func->callers.empty()) - funcs_callers.push_back(QueryFunc::CallersUpdate(previous_id_map.ToQuery(func->id), {}, previous_id_map.ToQuery(func->callers))); - } - }, - /*onAdded:*/[this, ¤t_id_map](IndexFunc* func) { - optional def_update = ToQuery(current_id_map, func->def); - if (def_update) - funcs_def_update.push_back(*def_update); - if (!func->declarations.empty()) - funcs_declarations.push_back(QueryFunc::DeclarationsUpdate(current_id_map.ToQuery(func->id), current_id_map.ToQuery(func->declarations))); - if (!func->derived.empty()) - funcs_derived.push_back(QueryFunc::DerivedUpdate(current_id_map.ToQuery(func->id), current_id_map.ToQuery(func->derived))); - if (!func->callers.empty()) - funcs_callers.push_back(QueryFunc::CallersUpdate(current_id_map.ToQuery(func->id), current_id_map.ToQuery(func->callers))); - }, - /*onFound:*/[this, &previous_id_map, ¤t_id_map](IndexFunc* previous_def, IndexFunc* current_def) { - optional previous_remapped_def = ToQuery(previous_id_map, previous_def->def); - optional current_remapped_def = ToQuery(current_id_map, current_def->def); - if (current_remapped_def && previous_remapped_def != current_remapped_def && !current_remapped_def->detailed_name.empty()) - funcs_def_update.push_back(*current_remapped_def); + CompareGroups( + previous_file.funcs, current_file.funcs, + /*onRemoved:*/ + [this, &previous_id_map](IndexFunc* func) { + if (func->def.definition_spelling) { + funcs_removed.push_back(func->def.usr); + } else { + if (!func->declarations.empty()) + funcs_declarations.push_back(QueryFunc::DeclarationsUpdate( + previous_id_map.ToQuery(func->id), {}, + previous_id_map.ToQuery(func->declarations))); + if (!func->derived.empty()) + funcs_derived.push_back(QueryFunc::DerivedUpdate( + previous_id_map.ToQuery(func->id), {}, + previous_id_map.ToQuery(func->derived))); + if (!func->callers.empty()) + funcs_callers.push_back(QueryFunc::CallersUpdate( + previous_id_map.ToQuery(func->id), {}, + previous_id_map.ToQuery(func->callers))); + } + }, + /*onAdded:*/ + [this, ¤t_id_map](IndexFunc* func) { + optional def_update = + ToQuery(current_id_map, func->def); + if (def_update) + funcs_def_update.push_back(*def_update); + if (!func->declarations.empty()) + funcs_declarations.push_back(QueryFunc::DeclarationsUpdate( + current_id_map.ToQuery(func->id), + current_id_map.ToQuery(func->declarations))); + if (!func->derived.empty()) + funcs_derived.push_back( + QueryFunc::DerivedUpdate(current_id_map.ToQuery(func->id), + current_id_map.ToQuery(func->derived))); + if (!func->callers.empty()) + funcs_callers.push_back( + QueryFunc::CallersUpdate(current_id_map.ToQuery(func->id), + current_id_map.ToQuery(func->callers))); + }, + /*onFound:*/ + [this, &previous_id_map, ¤t_id_map](IndexFunc* previous_def, + IndexFunc* current_def) { + optional previous_remapped_def = + ToQuery(previous_id_map, previous_def->def); + optional current_remapped_def = + ToQuery(current_id_map, current_def->def); + if (current_remapped_def && + previous_remapped_def != current_remapped_def && + !current_remapped_def->detailed_name.empty()) + funcs_def_update.push_back(*current_remapped_def); - PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations, QueryLocation); - PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId); - PROCESS_UPDATE_DIFF(QueryFuncId, funcs_callers, callers, QueryFuncRef); - }); + PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations, + QueryLocation); + PROCESS_UPDATE_DIFF(QueryFuncId, funcs_derived, derived, QueryFuncId); + PROCESS_UPDATE_DIFF(QueryFuncId, funcs_callers, callers, QueryFuncRef); + }); // Variables - CompareGroups(previous_file.vars, current_file.vars, - /*onRemoved:*/[this, &previous_id_map](IndexVar* var) { - if (var->def.definition_spelling) { - vars_removed.push_back(var->def.usr); - } - else { - if (!var->uses.empty()) - vars_uses.push_back(QueryVar::UsesUpdate(previous_id_map.ToQuery(var->id), {}, previous_id_map.ToQuery(var->uses))); - } - }, - /*onAdded:*/[this, ¤t_id_map](IndexVar* var) { - optional def_update = ToQuery(current_id_map, var->def); - if (def_update) - vars_def_update.push_back(*def_update); - if (!var->uses.empty()) - vars_uses.push_back(QueryVar::UsesUpdate(current_id_map.ToQuery(var->id), current_id_map.ToQuery(var->uses))); - }, - /*onFound:*/[this, &previous_id_map, ¤t_id_map](IndexVar* previous_def, IndexVar* current_def) { - optional previous_remapped_def = ToQuery(previous_id_map, previous_def->def); - optional current_remapped_def = ToQuery(current_id_map, current_def->def); - if (current_remapped_def && previous_remapped_def != current_remapped_def && !current_remapped_def->detailed_name.empty()) - vars_def_update.push_back(*current_remapped_def); + CompareGroups( + previous_file.vars, current_file.vars, + /*onRemoved:*/ + [this, &previous_id_map](IndexVar* var) { + if (var->def.definition_spelling) { + vars_removed.push_back(var->def.usr); + } else { + if (!var->uses.empty()) + vars_uses.push_back( + QueryVar::UsesUpdate(previous_id_map.ToQuery(var->id), {}, + previous_id_map.ToQuery(var->uses))); + } + }, + /*onAdded:*/ + [this, ¤t_id_map](IndexVar* var) { + optional def_update = + ToQuery(current_id_map, var->def); + if (def_update) + vars_def_update.push_back(*def_update); + if (!var->uses.empty()) + vars_uses.push_back( + QueryVar::UsesUpdate(current_id_map.ToQuery(var->id), + current_id_map.ToQuery(var->uses))); + }, + /*onFound:*/ + [this, &previous_id_map, ¤t_id_map](IndexVar* previous_def, + IndexVar* current_def) { + optional previous_remapped_def = + ToQuery(previous_id_map, previous_def->def); + optional current_remapped_def = + ToQuery(current_id_map, current_def->def); + if (current_remapped_def && + previous_remapped_def != current_remapped_def && + !current_remapped_def->detailed_name.empty()) + vars_def_update.push_back(*current_remapped_def); - PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, QueryLocation); - }); + PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, QueryLocation); + }); #undef PROCESS_UPDATE_DIFF } void IndexUpdate::Merge(const IndexUpdate& update) { - // This function runs on an indexer thread. +// This function runs on an indexer thread. -#define INDEX_UPDATE_APPEND(name) \ - AddRange(&name, update.name); -#define INDEX_UPDATE_MERGE(name) \ - AddMergeableRange(&name, update.name); +#define INDEX_UPDATE_APPEND(name) AddRange(&name, update.name); +#define INDEX_UPDATE_MERGE(name) AddMergeableRange(&name, update.name); INDEX_UPDATE_APPEND(files_removed); INDEX_UPDATE_APPEND(files_def_update); @@ -619,37 +643,12 @@ std::string IndexUpdate::ToString() { return output.GetString(); } - - - - - - - - - - - - - - - - - - - - - - - - - - // ------------------------ // QUERYDB THREAD FUNCTIONS // ------------------------ -void QueryDatabase::RemoveUsrs(SymbolKind usr_kind, const std::vector& to_remove) { +void QueryDatabase::RemoveUsrs(SymbolKind usr_kind, + const std::vector& to_remove) { // This function runs on the querydb thread. // When we remove an element, we just erase the state from the storage. We do @@ -690,20 +689,20 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind, const std::vector& to_r } void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) { - // This function runs on the querydb thread. +// This function runs on the querydb thread. - // Example types: - // storage_name => std::vector> - // merge_update => QueryType::DerivedUpdate => MergeableUpdate - // def => QueryType - // def->def_var_name => std::vector -#define HANDLE_MERGEABLE(update_var_name, def_var_name, storage_name) \ - for (auto merge_update : update->update_var_name) { \ - auto& def = storage_name[merge_update.id.id]; \ - if (!def) \ +// Example types: +// storage_name => std::vector> +// merge_update => QueryType::DerivedUpdate => +// MergeableUpdate def => QueryType +// def->def_var_name => std::vector +#define HANDLE_MERGEABLE(update_var_name, def_var_name, storage_name) \ + for (auto merge_update : update->update_var_name) { \ + auto& def = storage_name[merge_update.id.id]; \ + if (!def) \ continue; /* TODO: Should we continue or create an empty def? */ \ - AddRange(&def->def_var_name, merge_update.to_add); \ - RemoveRange(&def->def_var_name, merge_update.to_remove); \ + AddRange(&def->def_var_name, merge_update.to_add); \ + RemoveRange(&def->def_var_name, merge_update.to_remove); \ } RemoveUsrs(SymbolKind::File, update->files_removed); @@ -728,7 +727,8 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) { #undef HANDLE_MERGEABLE } -void QueryDatabase::ImportOrUpdate(const std::vector& updates) { +void QueryDatabase::ImportOrUpdate( + const std::vector& updates) { // This function runs on the querydb thread. for (auto& def : updates) { @@ -740,11 +740,13 @@ void QueryDatabase::ImportOrUpdate(const std::vector& upda existing = QueryFile(def.path); existing->def = def; - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::File, it->second.id, def.path); + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::File, + it->second.id, def.path); } } -void QueryDatabase::ImportOrUpdate(const std::vector& updates) { +void QueryDatabase::ImportOrUpdate( + const std::vector& updates) { // This function runs on the querydb thread. for (auto& def : updates) { @@ -763,11 +765,13 @@ void QueryDatabase::ImportOrUpdate(const std::vector& upda continue; existing->def = def; - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Type, it->second.id, def.detailed_name); + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Type, + it->second.id, def.detailed_name); } } -void QueryDatabase::ImportOrUpdate(const std::vector& updates) { +void QueryDatabase::ImportOrUpdate( + const std::vector& updates) { // This function runs on the querydb thread. for (auto& def : updates) { @@ -786,11 +790,13 @@ void QueryDatabase::ImportOrUpdate(const std::vector& upda continue; existing->def = def; - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Func, it->second.id, def.detailed_name); + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Func, + it->second.id, def.detailed_name); } } -void QueryDatabase::ImportOrUpdate(const std::vector& updates) { +void QueryDatabase::ImportOrUpdate( + const std::vector& updates) { // This function runs on the querydb thread. for (auto& def : updates) { @@ -810,17 +816,20 @@ void QueryDatabase::ImportOrUpdate(const std::vector& updat existing->def = def; if (!def.is_local) - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Var, it->second.id, def.detailed_name); + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Var, + it->second.id, def.detailed_name); } } -void QueryDatabase::UpdateDetailedNames(size_t* qualified_name_index, SymbolKind kind, size_t symbol_index, const std::string& name) { +void QueryDatabase::UpdateDetailedNames(size_t* qualified_name_index, + SymbolKind kind, + size_t symbol_index, + const std::string& name) { if (*qualified_name_index == -1) { detailed_names.push_back(name); symbols.push_back(SymbolIdx(kind, symbol_index)); *qualified_name_index = detailed_names.size() - 1; - } - else { + } else { detailed_names[*qualified_name_index] = name; } } @@ -831,31 +840,39 @@ IndexUpdate GetDelta(IndexFile previous, IndexFile current) { QueryDatabase db; IdMap previous_map(&db, previous.id_cache); IdMap current_map(&db, current.id_cache); - return IndexUpdate::CreateDelta(&previous_map, ¤t_map, &previous, ¤t); + return IndexUpdate::CreateDelta(&previous_map, ¤t_map, &previous, + ¤t); } TEST_CASE("remove defs") { IndexFile previous("foo.cc"); IndexFile current("foo.cc"); - previous.Resolve(previous.ToTypeId("usr1"))->def.definition_spelling = Range(Position(1, 0)); - previous.Resolve(previous.ToFuncId("usr2"))->def.definition_spelling = Range(Position(2, 0)); - previous.Resolve(previous.ToVarId("usr3"))->def.definition_spelling = Range(Position(3, 0)); + previous.Resolve(previous.ToTypeId("usr1"))->def.definition_spelling = + Range(Position(1, 0)); + previous.Resolve(previous.ToFuncId("usr2"))->def.definition_spelling = + Range(Position(2, 0)); + previous.Resolve(previous.ToVarId("usr3"))->def.definition_spelling = + Range(Position(3, 0)); IndexUpdate update = GetDelta(previous, current); - REQUIRE(update.types_removed == std::vector{ "usr1" }); - REQUIRE(update.funcs_removed == std::vector{ "usr2" }); - REQUIRE(update.vars_removed == std::vector{ "usr3" }); + REQUIRE(update.types_removed == std::vector{"usr1"}); + REQUIRE(update.funcs_removed == std::vector{"usr2"}); + REQUIRE(update.vars_removed == std::vector{"usr3"}); } TEST_CASE("do not remove ref-only defs") { IndexFile previous("foo.cc"); IndexFile current("foo.cc"); - previous.Resolve(previous.ToTypeId("usr1"))->uses.push_back(Range(Position(1, 0))); - previous.Resolve(previous.ToFuncId("usr2"))->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), false /*is_implicit*/)); - previous.Resolve(previous.ToVarId("usr3"))->uses.push_back(Range(Position(3, 0))); + previous.Resolve(previous.ToTypeId("usr1")) + ->uses.push_back(Range(Position(1, 0))); + previous.Resolve(previous.ToFuncId("usr2")) + ->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), + false /*is_implicit*/)); + previous.Resolve(previous.ToVarId("usr3")) + ->uses.push_back(Range(Position(3, 0))); IndexUpdate update = GetDelta(previous, current); @@ -871,8 +888,10 @@ TEST_CASE("func callers") { IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); - pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), false /*is_implicit*/)); - cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), false /*is_implicit*/)); + pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), + false /*is_implicit*/)); + cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), + false /*is_implicit*/)); IndexUpdate update = GetDelta(previous, current); @@ -880,7 +899,8 @@ TEST_CASE("func callers") { REQUIRE(update.funcs_callers.size() == 1); REQUIRE(update.funcs_callers[0].id == QueryFuncId(0)); REQUIRE(update.funcs_callers[0].to_remove.size() == 1); - REQUIRE(update.funcs_callers[0].to_remove[0].loc.range == Range(Position(1, 0))); + REQUIRE(update.funcs_callers[0].to_remove[0].loc.range == + Range(Position(1, 0))); REQUIRE(update.funcs_callers[0].to_add.size() == 1); REQUIRE(update.funcs_callers[0].to_add[0].loc.range == Range(Position(2, 0))); } @@ -912,18 +932,24 @@ TEST_CASE("apply delta") { IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); - pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), false /*is_implicit*/)); - pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), false /*is_implicit*/)); - cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(4, 0)), false /*is_implicit*/)); - cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(5, 0)), false /*is_implicit*/)); + pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), + false /*is_implicit*/)); + pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), + false /*is_implicit*/)); + cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(4, 0)), + false /*is_implicit*/)); + cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(5, 0)), + false /*is_implicit*/)); QueryDatabase db; IdMap previous_map(&db, previous.id_cache); IdMap current_map(&db, current.id_cache); REQUIRE(db.funcs.size() == 1); - IndexUpdate import_update = IndexUpdate::CreateDelta(nullptr, &previous_map, nullptr, &previous); - IndexUpdate delta_update = IndexUpdate::CreateDelta(&previous_map, ¤t_map, &previous, ¤t); + IndexUpdate import_update = + IndexUpdate::CreateDelta(nullptr, &previous_map, nullptr, &previous); + IndexUpdate delta_update = IndexUpdate::CreateDelta( + &previous_map, ¤t_map, &previous, ¤t); db.ApplyIndexUpdate(&import_update); REQUIRE(db.funcs[0]->callers.size() == 2); diff --git a/src/query.h b/src/query.h index 0cb02444..8edd865b 100644 --- a/src/query.h +++ b/src/query.h @@ -20,22 +20,14 @@ using QueryTypeId = Id; using QueryFuncId = Id; using QueryVarId = Id; - - - - - struct IdMap; - - struct QueryLocation { QueryFileId path; Range range; - QueryLocation() {} // Do not use, needed for reflect. - QueryLocation(QueryFileId path, Range range) - : path(path), range(range) {} + QueryLocation() {} // Do not use, needed for reflect. + QueryLocation(QueryFileId path, Range range) : path(path), range(range) {} QueryLocation OffsetStartColumn(int16_t offset) const { QueryLocation result = *this; @@ -45,11 +37,11 @@ struct QueryLocation { bool operator==(const QueryLocation& other) const { // Note: We ignore |is_interesting|. - return - path == other.path && - range == other.range; + return path == other.path && range == other.range; + } + bool operator!=(const QueryLocation& other) const { + return !(*this == other); } - bool operator!=(const QueryLocation& other) const { return !(*this == other); } bool operator<(const QueryLocation& o) const { if (path < o.path) return true; @@ -66,7 +58,9 @@ struct SymbolIdx { SymbolKind kind; size_t idx; - SymbolIdx() : kind(SymbolKind::Invalid), idx((size_t)-1) {} // Default ctor needed by stdlib. Do not use. + SymbolIdx() + : kind(SymbolKind::Invalid), + idx((size_t)-1) {} // Default ctor needed by stdlib. Do not use. SymbolIdx(SymbolKind kind, uint64_t idx) : kind(kind), idx(idx) {} bool operator==(const SymbolIdx& that) const { @@ -85,7 +79,7 @@ struct SymbolRef { SymbolIdx idx; QueryLocation loc; - SymbolRef() {} // Do not use, needed for reflect. + SymbolRef() {} // Do not use, needed for reflect. SymbolRef(SymbolIdx idx, QueryLocation loc) : idx(idx), loc(loc) {} bool operator==(const SymbolRef& that) const { @@ -108,11 +102,13 @@ struct QueryFuncRef { bool has_id() const { return id_.id != -1; } - QueryFuncRef() {} // Do not use, needed for reflect. - QueryFuncRef(QueryFuncId id, QueryLocation loc, bool is_implicit) : id_(id), loc(loc), is_implicit(is_implicit) {} + QueryFuncRef() {} // Do not use, needed for reflect. + QueryFuncRef(QueryFuncId id, QueryLocation loc, bool is_implicit) + : id_(id), loc(loc), is_implicit(is_implicit) {} bool operator==(const QueryFuncRef& that) const { - return id_ == that.id_ && loc == that.loc && is_implicit == that.is_implicit; + return id_ == that.id_ && loc == that.loc && + is_implicit == that.is_implicit; } bool operator!=(const QueryFuncRef& that) const { return !(*this == that); } bool operator<(const QueryFuncRef& that) const { @@ -120,7 +116,8 @@ struct QueryFuncRef { return true; if (id_ == that.id_ && loc.range.start < that.loc.range.start) return true; - return id_ == that.id_ && loc.range.start == that.loc.range.start && is_implicit < that.is_implicit; + return id_ == that.id_ && loc.range.start == that.loc.range.start && + is_implicit < that.is_implicit; } }; MAKE_REFLECT_STRUCT(QueryFuncRef, id_, loc, is_implicit); @@ -135,7 +132,7 @@ MAKE_REFLECT_STRUCT(QueryFuncRef, id_, loc, is_implicit); // that it can be merged with other updates before actually being applied to // the main database. See |MergeableUpdate|. -template +template struct MergeableUpdate { // The type/func/var which is getting new usages. TId id; @@ -144,11 +141,13 @@ struct MergeableUpdate { std::vector to_remove; MergeableUpdate(TId id, const std::vector& to_add) - : id(id), to_add(to_add) {} - MergeableUpdate(TId id, const std::vector& to_add, const std::vector& to_remove) - : id(id), to_add(to_add), to_remove(to_remove) {} + : id(id), to_add(to_add) {} + MergeableUpdate(TId id, + const std::vector& to_add, + const std::vector& to_remove) + : id(id), to_add(to_add), to_remove(to_remove) {} }; -template +template void Reflect(TVisitor& visitor, MergeableUpdate& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER(id); @@ -178,7 +177,10 @@ struct QueryFile { MAKE_REFLECT_STRUCT(QueryFile::Def, path, outline, all_symbols); struct QueryType { - using DefUpdate = TypeDefDefinitionData; + using DefUpdate = TypeDefDefinitionData; using DerivedUpdate = MergeableUpdate; using InstancesUpdate = MergeableUpdate; using UsesUpdate = MergeableUpdate; @@ -193,7 +195,11 @@ struct QueryType { }; struct QueryFunc { - using DefUpdate = FuncDefDefinitionData; + using DefUpdate = FuncDefDefinitionData; using DeclarationsUpdate = MergeableUpdate; using DerivedUpdate = MergeableUpdate; using CallersUpdate = MergeableUpdate; @@ -208,7 +214,8 @@ struct QueryFunc { }; struct QueryVar { - using DefUpdate = VarDefDefinitionData; + using DefUpdate = + VarDefDefinitionData; using UsesUpdate = MergeableUpdate; DefUpdate def; @@ -221,7 +228,10 @@ struct QueryVar { struct IndexUpdate { // Creates a new IndexUpdate based on the delta from previous to current. If // no delta computation should be done just pass null for previous. - static IndexUpdate CreateDelta(const IdMap* previous_id_map, const IdMap* current_id_map, IndexFile* previous, IndexFile* current); + static IndexUpdate CreateDelta(const IdMap* previous_id_map, + const IdMap* current_id_map, + IndexFile* previous, + IndexFile* current); // Merge |update| into this update; this can reduce overhead / index update // work can be parallelized. @@ -257,13 +267,27 @@ struct IndexUpdate { // Creates an index update assuming that |previous| is already // in the index, so only the delta between |previous| and |current| // will be applied. - IndexUpdate(const IdMap& previous_id_map, const IdMap& current_id_map, IndexFile& previous, IndexFile& current); + IndexUpdate(const IdMap& previous_id_map, + const IdMap& current_id_map, + IndexFile& previous, + IndexFile& current); }; -// NOTICE: We're not reflecting on files_removed or files_def_update, it is too much output when logging +// NOTICE: We're not reflecting on files_removed or files_def_update, it is too +// much output when logging MAKE_REFLECT_STRUCT(IndexUpdate, - types_removed, types_def_update, types_derived, types_instances, types_uses, - funcs_removed, funcs_def_update, funcs_declarations, funcs_derived, funcs_callers, - vars_removed, vars_def_update, vars_uses); + types_removed, + types_def_update, + types_derived, + types_instances, + types_uses, + funcs_removed, + funcs_def_update, + funcs_declarations, + funcs_derived, + funcs_callers, + vars_removed, + vars_def_update, + vars_uses); // The query database is heavily optimized for fast queries. It is stored // in-memory. @@ -295,12 +319,12 @@ struct QueryDatabase { void ImportOrUpdate(const std::vector& updates); void ImportOrUpdate(const std::vector& updates); void ImportOrUpdate(const std::vector& updates); - void UpdateDetailedNames(size_t* qualified_name_index, SymbolKind kind, size_t symbol_index, const std::string& name); + void UpdateDetailedNames(size_t* qualified_name_index, + SymbolKind kind, + size_t symbol_index, + const std::string& name); }; - - - struct IdMap { const IdCache& local_ids; QueryFileId primary_file; @@ -324,12 +348,14 @@ struct IdMap { std::vector ToQuery(std::vector ids) const; std::vector ToQuery(std::vector ids) const; std::vector ToQuery(std::vector refs) const; - std::vector ToQuery(std::vector decls) const; + std::vector ToQuery( + std::vector decls) const; SymbolIdx ToSymbol(IndexTypeId id) const; SymbolIdx ToSymbol(IndexFuncId id) const; SymbolIdx ToSymbol(IndexVarId id) const; -private: + + private: spp::sparse_hash_map cached_type_ids_; spp::sparse_hash_map cached_func_ids_; spp::sparse_hash_map cached_var_ids_; diff --git a/src/query_utils.cc b/src/query_utils.cc index ccbf8004..11db68d6 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -13,159 +13,170 @@ int ComputeRangeSize(const Range& range) { } // namespace -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryTypeId& id) { +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const QueryTypeId& id) { optional& type = db->types[id.id]; if (type) return type->def.definition_spelling; return nullopt; } -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryFuncId& id) { +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const QueryFuncId& id) { optional& func = db->funcs[id.id]; if (func) return func->def.definition_spelling; return nullopt; } -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryVarId& id) { +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const QueryVarId& id) { optional& var = db->vars[id.id]; if (var) return var->def.definition_spelling; return nullopt; } -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const SymbolIdx& symbol) { +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (type) - return type->def.definition_spelling; - break; - } - case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) - return func->def.definition_spelling; - break; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->def.definition_spelling; - break; - } - case SymbolKind::File: - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } + case SymbolKind::Type: { + optional& type = db->types[symbol.idx]; + if (type) + return type->def.definition_spelling; + break; + } + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (func) + return func->def.definition_spelling; + break; + } + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (var) + return var->def.definition_spelling; + break; + } + case SymbolKind::File: + case SymbolKind::Invalid: { + assert(false && "unexpected"); + break; + } } return nullopt; } -optional GetDefinitionExtentOfSymbol(QueryDatabase* db, const SymbolIdx& symbol) { +optional GetDefinitionExtentOfSymbol(QueryDatabase* db, + const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (type) - return type->def.definition_extent; - break; - } - case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) - return func->def.definition_extent; - break; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->def.definition_extent; - break; - } - case SymbolKind::File: { - return QueryLocation(QueryFileId(symbol.idx), Range(Position(1, 1), Position(1, 1))); - } - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } + case SymbolKind::Type: { + optional& type = db->types[symbol.idx]; + if (type) + return type->def.definition_extent; + break; + } + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (func) + return func->def.definition_extent; + break; + } + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (var) + return var->def.definition_extent; + break; + } + case SymbolKind::File: { + return QueryLocation(QueryFileId(symbol.idx), + Range(Position(1, 1), Position(1, 1))); + } + case SymbolKind::Invalid: { + assert(false && "unexpected"); + break; + } } return nullopt; } std::string GetHoverForSymbol(QueryDatabase* db, const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (type) - return type->def.detailed_name; - break; - } - case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) - return func->def.detailed_name; - break; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->def.detailed_name; - break; - } - case SymbolKind::File: - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } + case SymbolKind::Type: { + optional& type = db->types[symbol.idx]; + if (type) + return type->def.detailed_name; + break; + } + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (func) + return func->def.detailed_name; + break; + } + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (var) + return var->def.detailed_name; + break; + } + case SymbolKind::File: + case SymbolKind::Invalid: { + assert(false && "unexpected"); + break; + } } return ""; } -optional GetDeclarationFileForSymbol(QueryDatabase* db, const SymbolIdx& symbol) { +optional GetDeclarationFileForSymbol(QueryDatabase* db, + const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (type && type->def.definition_spelling) - return type->def.definition_spelling->path; - break; - } - case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) { - if (!func->declarations.empty()) - return func->declarations[0].path; - if (func->def.definition_spelling) - return func->def.definition_spelling->path; + case SymbolKind::Type: { + optional& type = db->types[symbol.idx]; + if (type && type->def.definition_spelling) + return type->def.definition_spelling->path; + break; + } + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (func) { + if (!func->declarations.empty()) + return func->declarations[0].path; + if (func->def.definition_spelling) + return func->def.definition_spelling->path; + } + break; + } + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (var && var->def.definition_spelling) + return var->def.definition_spelling->path; + break; + } + case SymbolKind::File: { + return QueryFileId(symbol.idx); + } + case SymbolKind::Invalid: { + assert(false && "unexpected"); + break; } - break; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var && var->def.definition_spelling) - return var->def.definition_spelling->path; - break; - } - case SymbolKind::File: { - return QueryFileId(symbol.idx); - } - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } } return nullopt; } -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& refs) { +std::vector ToQueryLocation( + QueryDatabase* db, + const std::vector& refs) { std::vector locs; locs.reserve(refs.size()); for (const QueryFuncRef& ref : refs) locs.push_back(ref.loc); return locs; } -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& ids) { +std::vector ToQueryLocation( + QueryDatabase* db, + const std::vector& ids) { std::vector locs; locs.reserve(ids.size()); for (const QueryTypeId& id : ids) { @@ -175,7 +186,9 @@ std::vector ToQueryLocation(QueryDatabase* db, const std::vector< } return locs; } -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& ids) { +std::vector ToQueryLocation( + QueryDatabase* db, + const std::vector& ids) { std::vector locs; locs.reserve(ids.size()); for (const QueryFuncId& id : ids) { @@ -185,7 +198,8 @@ std::vector ToQueryLocation(QueryDatabase* db, const std::vector< } return locs; } -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& ids) { +std::vector ToQueryLocation(QueryDatabase* db, + const std::vector& ids) { std::vector locs; locs.reserve(ids.size()); for (const QueryVarId& id : ids) { @@ -196,81 +210,84 @@ std::vector ToQueryLocation(QueryDatabase* db, const std::vector< return locs; } - - -std::vector GetUsesOfSymbol(QueryDatabase* db, const SymbolIdx& symbol) { +std::vector GetUsesOfSymbol(QueryDatabase* db, + const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (type) - return type->uses; - break; - } - case SymbolKind::Func: { - // TODO: the vector allocation could be avoided. - optional& func = db->funcs[symbol.idx]; - if (func) { - std::vector result = ToQueryLocation(db, func->callers); - AddRange(&result, func->declarations); - if (func->def.definition_spelling) - result.push_back(*func->def.definition_spelling); - return result; + case SymbolKind::Type: { + optional& type = db->types[symbol.idx]; + if (type) + return type->uses; + break; + } + case SymbolKind::Func: { + // TODO: the vector allocation could be avoided. + optional& func = db->funcs[symbol.idx]; + if (func) { + std::vector result = ToQueryLocation(db, func->callers); + AddRange(&result, func->declarations); + if (func->def.definition_spelling) + result.push_back(*func->def.definition_spelling); + return result; + } + break; + } + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (var) + return var->uses; + break; + } + case SymbolKind::File: + case SymbolKind::Invalid: { + assert(false && "unexpected"); + break; } - break; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->uses; - break; - } - case SymbolKind::File: - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } } return {}; } -std::vector GetDeclarationsOfSymbolForGotoDefinition(QueryDatabase* db, const SymbolIdx& symbol) { +std::vector GetDeclarationsOfSymbolForGotoDefinition( + QueryDatabase* db, + const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: { - // Returning the definition spelling of a type is a hack (and is why the - // function has the postfix `ForGotoDefintion`, but it lets the user - // jump to the start of a type if clicking goto-definition on the same - // type from within the type definition. - optional& type = db->types[symbol.idx]; - if (type) { - optional declaration = type->def.definition_spelling; - if (declaration) - return { *declaration }; + case SymbolKind::Type: { + // Returning the definition spelling of a type is a hack (and is why the + // function has the postfix `ForGotoDefintion`, but it lets the user + // jump to the start of a type if clicking goto-definition on the same + // type from within the type definition. + optional& type = db->types[symbol.idx]; + if (type) { + optional declaration = type->def.definition_spelling; + if (declaration) + return {*declaration}; + } + break; } - break; - } - case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) - return func->declarations; - break; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) { - optional declaration = var->def.declaration; - if (declaration) - return { *declaration }; + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (func) + return func->declarations; + break; } - break; - } - default: - break; + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (var) { + optional declaration = var->def.declaration; + if (declaration) + return {*declaration}; + } + break; + } + default: + break; } return {}; } -optional GetBaseDefinitionOrDeclarationSpelling(QueryDatabase* db, QueryFunc& func) { +optional GetBaseDefinitionOrDeclarationSpelling( + QueryDatabase* db, + QueryFunc& func) { if (!func.def.base) return nullopt; optional& base = db->funcs[func.def.base->id]; @@ -316,7 +333,8 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { return false; } -std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, QueryFunc& root) { +std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, + QueryFunc& root) { std::vector callers; optional func_id = root.def.base; @@ -332,7 +350,8 @@ std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, Query return callers; } -std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, QueryFunc& root) { +std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, + QueryFunc& root) { std::vector callers; std::queue queue; @@ -351,7 +370,8 @@ std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, Qu return callers; } -optional GetLsPosition(WorkingFile* working_file, const Position& position) { +optional GetLsPosition(WorkingFile* working_file, + const Position& position) { if (!working_file) return lsPosition(position.line - 1, position.column - 1); @@ -365,12 +385,14 @@ optional GetLsPosition(WorkingFile* working_file, const Position& po optional GetLsRange(WorkingFile* working_file, const Range& location) { if (!working_file) { return lsRange( - lsPosition(location.start.line - 1, location.start.column - 1), - lsPosition(location.end.line - 1, location.end.column - 1)); + lsPosition(location.start.line - 1, location.start.column - 1), + lsPosition(location.end.line - 1, location.end.column - 1)); } - optional start = working_file->GetBufferLineFromIndexLine(location.start.line); - optional end = working_file->GetBufferLineFromIndexLine(location.end.line); + optional start = + working_file->GetBufferLineFromIndexLine(location.start.line); + optional end = + working_file->GetBufferLineFromIndexLine(location.end.line); if (!start || !end) return nullopt; @@ -383,18 +405,18 @@ optional GetLsRange(WorkingFile* working_file, const Range& location) { if (*end < *start) *end = *start + (location.end.line - location.start.line); - return lsRange( - lsPosition(*start - 1, location.start.column - 1), - lsPosition(*end - 1, location.end.column - 1)); + return lsRange(lsPosition(*start - 1, location.start.column - 1), + lsPosition(*end - 1, location.end.column - 1)); } -lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id, std::string* path) { +lsDocumentUri GetLsDocumentUri(QueryDatabase* db, + QueryFileId file_id, + std::string* path) { optional& file = db->files[file_id.id]; if (file) { *path = file->def.path; return lsDocumentUri::FromPath(*path); - } - else { + } else { *path = ""; return lsDocumentUri::FromPath(""); } @@ -404,25 +426,31 @@ lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id) { optional& file = db->files[file_id.id]; if (file) { return lsDocumentUri::FromPath(file->def.path); - } - else { + } else { return lsDocumentUri::FromPath(""); } } -optional GetLsLocation(QueryDatabase* db, WorkingFiles* working_files, const QueryLocation& location) { +optional GetLsLocation(QueryDatabase* db, + WorkingFiles* working_files, + const QueryLocation& location) { std::string path; lsDocumentUri uri = GetLsDocumentUri(db, location.path, &path); - optional range = GetLsRange(working_files->GetFileByFilename(path), location.range); + optional range = + GetLsRange(working_files->GetFileByFilename(path), location.range); if (!range) return nullopt; return lsLocation(uri, *range); } -NonElidedVector GetLsLocations(QueryDatabase* db, WorkingFiles* working_files, const std::vector& locations) { +NonElidedVector GetLsLocations( + QueryDatabase* db, + WorkingFiles* working_files, + const std::vector& locations) { std::unordered_set unique_locations; for (const QueryLocation& query_location : locations) { - optional location = GetLsLocation(db, working_files, query_location); + optional location = + GetLsLocation(db, working_files, query_location); if (!location) continue; unique_locations.insert(*location); @@ -435,75 +463,77 @@ NonElidedVector GetLsLocations(QueryDatabase* db, WorkingFiles* work } // Returns a symbol. The symbol will have *NOT* have a location assigned. -optional GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, SymbolIdx symbol) { +optional GetSymbolInfo(QueryDatabase* db, + WorkingFiles* working_files, + SymbolIdx symbol) { switch (symbol.kind) { - case SymbolKind::File: { - optional& file = db->files[symbol.idx]; - if (!file) - return nullopt; + case SymbolKind::File: { + optional& file = db->files[symbol.idx]; + if (!file) + return nullopt; - lsSymbolInformation info; - info.name = file->def.path; - info.kind = lsSymbolKind::File; - return info; - } - case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (!type) - return nullopt; - - lsSymbolInformation info; - info.name = type->def.short_name; - if (type->def.detailed_name != type->def.short_name) - info.containerName = type->def.detailed_name; - info.kind = lsSymbolKind::Class; - return info; - } - case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (!func) - return nullopt; - - lsSymbolInformation info; - info.name = func->def.short_name; - info.containerName = func->def.detailed_name; - info.kind = lsSymbolKind::Function; - - if (func->def.declaring_type.has_value()) { - optional& container = db->types[func->def.declaring_type->id]; - if (container) - info.kind = lsSymbolKind::Method; + lsSymbolInformation info; + info.name = file->def.path; + info.kind = lsSymbolKind::File; + return info; } + case SymbolKind::Type: { + optional& type = db->types[symbol.idx]; + if (!type) + return nullopt; - return info; - } - case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (!var) + lsSymbolInformation info; + info.name = type->def.short_name; + if (type->def.detailed_name != type->def.short_name) + info.containerName = type->def.detailed_name; + info.kind = lsSymbolKind::Class; + return info; + } + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (!func) + return nullopt; + + lsSymbolInformation info; + info.name = func->def.short_name; + info.containerName = func->def.detailed_name; + info.kind = lsSymbolKind::Function; + + if (func->def.declaring_type.has_value()) { + optional& container = + db->types[func->def.declaring_type->id]; + if (container) + info.kind = lsSymbolKind::Method; + } + + return info; + } + case SymbolKind::Var: { + optional& var = db->vars[symbol.idx]; + if (!var) + return nullopt; + + lsSymbolInformation info; + info.name += var->def.short_name; + info.containerName = var->def.detailed_name; + info.kind = lsSymbolKind::Variable; + return info; + } + case SymbolKind::Invalid: { return nullopt; - - lsSymbolInformation info; - info.name += var->def.short_name; - info.containerName = var->def.detailed_name; - info.kind = lsSymbolKind::Variable; - return info; - } - case SymbolKind::Invalid: { - return nullopt; - } + } }; return nullopt; } -void AddCodeLens( - const char* singular, - const char* plural, - CommonCodeLensParams* common, - QueryLocation loc, - const std::vector& uses, - optional excluded, - bool force_display) { +void AddCodeLens(const char* singular, + const char* plural, + CommonCodeLensParams* common, + QueryLocation loc, + const std::vector& uses, + optional excluded, + bool force_display) { TCodeLens code_lens; optional range = GetLsRange(common->working_file, loc.range); if (!range) @@ -519,13 +549,14 @@ void AddCodeLens( for (const QueryLocation& use : uses) { if (excluded == use) continue; - optional location = GetLsLocation(common->db, common->working_files, use); + optional location = + GetLsLocation(common->db, common->working_files, use); if (!location) continue; unique_uses.insert(*location); } code_lens.command->arguments.locations.assign(unique_uses.begin(), - unique_uses.end()); + unique_uses.end()); // User visible label size_t num_usages = unique_uses.size(); @@ -539,11 +570,15 @@ void AddCodeLens( common->result->push_back(code_lens); } -lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, WorkingFiles* working_files, const std::vector& locations, const std::string& new_text) { +lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, + WorkingFiles* working_files, + const std::vector& locations, + const std::string& new_text) { std::unordered_map path_to_edit; for (auto& location : locations) { - optional ls_location = GetLsLocation(db, working_files, location); + optional ls_location = + GetLsLocation(db, working_files, location); if (!ls_location) continue; @@ -555,11 +590,13 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, WorkingFiles* working_file continue; const std::string& path = file->def.path; - path_to_edit[location.path].textDocument.uri = lsDocumentUri::FromPath(path); + path_to_edit[location.path].textDocument.uri = + lsDocumentUri::FromPath(path); WorkingFile* working_file = working_files->GetFileByFilename(path); if (working_file) - path_to_edit[location.path].textDocument.version = working_file->version; + path_to_edit[location.path].textDocument.version = + working_file->version; } lsTextEdit edit; @@ -572,21 +609,23 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, WorkingFiles* working_file edits.push_back(edit); } - lsWorkspaceEdit edit; for (const auto& changes : path_to_edit) edit.documentChanges.push_back(changes.second); return edit; } -std::vector FindSymbolsAtLocation(WorkingFile* working_file, QueryFile* file, lsPosition position) { +std::vector FindSymbolsAtLocation(WorkingFile* working_file, + QueryFile* file, + lsPosition position) { std::vector symbols; symbols.reserve(1); int target_line = position.line + 1; int target_column = position.character + 1; if (working_file) { - optional index_line = working_file->GetIndexLineFromBufferLine(target_line); + optional index_line = + working_file->GetIndexLineFromBufferLine(target_line); if (index_line) target_line = *index_line; } @@ -602,20 +641,25 @@ std::vector FindSymbolsAtLocation(WorkingFile* working_file, QueryFil // // Order functions before other types, which makes goto definition work // better on constructors. - std::sort(symbols.begin(), symbols.end(), [](const SymbolRef& a, const SymbolRef& b) { - int a_size = ComputeRangeSize(a.loc.range); - int b_size = ComputeRangeSize(b.loc.range); + std::sort(symbols.begin(), symbols.end(), + [](const SymbolRef& a, const SymbolRef& b) { + int a_size = ComputeRangeSize(a.loc.range); + int b_size = ComputeRangeSize(b.loc.range); - if (a_size == b_size) - return a.idx.kind != b.idx.kind && a.idx.kind == SymbolKind::Func; + if (a_size == b_size) + return a.idx.kind != b.idx.kind && + a.idx.kind == SymbolKind::Func; - return a_size < b_size; - }); + return a_size < b_size; + }); return symbols; } -NonElidedVector BuildParentInheritanceHierarchyForType(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) { +NonElidedVector +BuildParentInheritanceHierarchyForType(QueryDatabase* db, + WorkingFiles* working_files, + QueryTypeId root) { optional& root_type = db->types[root.id]; if (!root_type) return {}; @@ -631,8 +675,10 @@ NonElidedVector BuildParentInheritanceHi Out_CqueryTypeHierarchyTree::TypeEntry parent_entry; parent_entry.name = parent_type->def.detailed_name; if (parent_type->def.definition_spelling) - parent_entry.location = GetLsLocation(db, working_files, *parent_type->def.definition_spelling); - parent_entry.children = BuildParentInheritanceHierarchyForType(db, working_files, parent_id); + parent_entry.location = GetLsLocation( + db, working_files, *parent_type->def.definition_spelling); + parent_entry.children = + BuildParentInheritanceHierarchyForType(db, working_files, parent_id); parent_entries.push_back(parent_entry); } @@ -640,8 +686,10 @@ NonElidedVector BuildParentInheritanceHi return parent_entries; } - -optional BuildInheritanceHierarchyForType(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root_id) { +optional +BuildInheritanceHierarchyForType(QueryDatabase* db, + WorkingFiles* working_files, + QueryTypeId root_id) { optional& root_type = db->types[root_id.id]; if (!root_type) return nullopt; @@ -651,7 +699,8 @@ optional BuildInheritanceHierarchyForTyp // Name and location. entry.name = root_type->def.detailed_name; if (root_type->def.definition_spelling) - entry.location = GetLsLocation(db, working_files, *root_type->def.definition_spelling); + entry.location = + GetLsLocation(db, working_files, *root_type->def.definition_spelling); entry.children.reserve(root_type->derived.size()); @@ -659,13 +708,15 @@ optional BuildInheritanceHierarchyForTyp Out_CqueryTypeHierarchyTree::TypeEntry base; base.name = "[[Base]]"; base.location = entry.location; - base.children = BuildParentInheritanceHierarchyForType(db, working_files, root_id); + base.children = + BuildParentInheritanceHierarchyForType(db, working_files, root_id); if (!base.children.empty()) entry.children.push_back(base); // Add derived. for (QueryTypeId derived : root_type->derived) { - auto derived_entry = BuildInheritanceHierarchyForType(db, working_files, derived); + auto derived_entry = + BuildInheritanceHierarchyForType(db, working_files, derived); if (derived_entry) entry.children.push_back(*derived_entry); } @@ -673,8 +724,10 @@ optional BuildInheritanceHierarchyForTyp return entry; } - -NonElidedVector BuildParentInheritanceHierarchyForFunc(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root) { +NonElidedVector +BuildParentInheritanceHierarchyForFunc(QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root) { optional& root_func = db->funcs[root.id]; if (!root_func || !root_func->def.base) return {}; @@ -686,16 +739,20 @@ NonElidedVector BuildParentInheritanceHi Out_CqueryTypeHierarchyTree::TypeEntry parent_entry; parent_entry.name = parent_func->def.detailed_name; if (parent_func->def.definition_spelling) - parent_entry.location = GetLsLocation(db, working_files, *parent_func->def.definition_spelling); - parent_entry.children = BuildParentInheritanceHierarchyForFunc(db, working_files, *root_func->def.base); + parent_entry.location = + GetLsLocation(db, working_files, *parent_func->def.definition_spelling); + parent_entry.children = BuildParentInheritanceHierarchyForFunc( + db, working_files, *root_func->def.base); NonElidedVector entries; entries.push_back(parent_entry); return entries; } - -optional BuildInheritanceHierarchyForFunc(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root_id) { +optional +BuildInheritanceHierarchyForFunc(QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root_id) { optional& root_func = db->funcs[root_id.id]; if (!root_func) return nullopt; @@ -705,7 +762,8 @@ optional BuildInheritanceHierarchyForFun // Name and location. entry.name = root_func->def.detailed_name; if (root_func->def.definition_spelling) - entry.location = GetLsLocation(db, working_files, *root_func->def.definition_spelling); + entry.location = + GetLsLocation(db, working_files, *root_func->def.definition_spelling); entry.children.reserve(root_func->derived.size()); @@ -713,13 +771,15 @@ optional BuildInheritanceHierarchyForFun Out_CqueryTypeHierarchyTree::TypeEntry base; base.name = "[[Base]]"; base.location = entry.location; - base.children = BuildParentInheritanceHierarchyForFunc(db, working_files, root_id); + base.children = + BuildParentInheritanceHierarchyForFunc(db, working_files, root_id); if (!base.children.empty()) entry.children.push_back(base); // Add derived. for (QueryFuncId derived : root_func->derived) { - auto derived_entry = BuildInheritanceHierarchyForFunc(db, working_files, derived); + auto derived_entry = + BuildInheritanceHierarchyForFunc(db, working_files, derived); if (derived_entry) entry.children.push_back(*derived_entry); } @@ -727,13 +787,17 @@ optional BuildInheritanceHierarchyForFun return entry; } -NonElidedVector BuildInitialCallTree(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root) { +NonElidedVector BuildInitialCallTree( + QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root) { optional& root_func = db->funcs[root.id]; if (!root_func) return {}; if (!root_func->def.definition_spelling) return {}; - optional def_loc = GetLsLocation(db, working_files, *root_func->def.definition_spelling); + optional def_loc = + GetLsLocation(db, working_files, *root_func->def.definition_spelling); if (!def_loc) return {}; @@ -747,12 +811,17 @@ NonElidedVector BuildInitialCallTree(QueryDatabas return result; } -NonElidedVector BuildExpandCallTree(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root) { +NonElidedVector BuildExpandCallTree( + QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root) { optional& root_func = db->funcs[root.id]; if (!root_func) return {}; - auto format_location = [&](const lsLocation& location, optional declaring_type) -> std::string { + auto format_location = + [&](const lsLocation& location, + optional declaring_type) -> std::string { std::string base; if (declaring_type) { @@ -774,8 +843,10 @@ NonElidedVector BuildExpandCallTree(QueryDatabase NonElidedVector result; std::unordered_set seen_locations; - auto handle_caller = [&](QueryFuncRef caller, Out_CqueryCallTree::CallType call_type) { - optional call_location = GetLsLocation(db, working_files, caller.loc); + auto handle_caller = [&](QueryFuncRef caller, + Out_CqueryCallTree::CallType call_type) { + optional call_location = + GetLsLocation(db, working_files, caller.loc); if (!call_location) return; @@ -803,14 +874,15 @@ NonElidedVector BuildExpandCallTree(QueryDatabase return; Out_CqueryCallTree::CallEntry call_entry; - call_entry.name = call_func->def.short_name + " (" + format_location(*call_location, call_func->def.declaring_type) + ")"; + call_entry.name = + call_func->def.short_name + " (" + + format_location(*call_location, call_func->def.declaring_type) + ")"; call_entry.usr = call_func->def.usr; call_entry.location = *call_location; call_entry.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, *call_func); call_entry.callType = call_type; result.push_back(call_entry); - } - else { + } else { // TODO: See if we can do a better job here. Need more information from // the indexer. Out_CqueryCallTree::CallEntry call_entry; @@ -823,9 +895,12 @@ NonElidedVector BuildExpandCallTree(QueryDatabase } }; - std::vector base_callers = GetCallersForAllBaseFunctions(db, *root_func); - std::vector derived_callers = GetCallersForAllDerivedFunctions(db, *root_func); - result.reserve(root_func->callers.size() + base_callers.size() + derived_callers.size()); + std::vector base_callers = + GetCallersForAllBaseFunctions(db, *root_func); + std::vector derived_callers = + GetCallersForAllDerivedFunctions(db, *root_func); + result.reserve(root_func->callers.size() + base_callers.size() + + derived_callers.size()); for (QueryFuncRef caller : root_func->callers) handle_caller(caller, Out_CqueryCallTree::CallType::Direct); diff --git a/src/query_utils.h b/src/query_utils.h index f4a6011f..c5f84596 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -7,31 +7,59 @@ #include -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryTypeId& id); -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryFuncId& id); -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryVarId& id); -optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const SymbolIdx& symbol); -optional GetDefinitionExtentOfSymbol(QueryDatabase* db, const SymbolIdx& symbol); +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const QueryTypeId& id); +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const QueryFuncId& id); +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const QueryVarId& id); +optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, + const SymbolIdx& symbol); +optional GetDefinitionExtentOfSymbol(QueryDatabase* db, + const SymbolIdx& symbol); std::string GetHoverForSymbol(QueryDatabase* db, const SymbolIdx& symbol); -optional GetDeclarationFileForSymbol(QueryDatabase* db, const SymbolIdx& symbol); -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& refs); -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& ids); -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& ids); -std::vector ToQueryLocation(QueryDatabase* db, const std::vector& ids); -std::vector GetUsesOfSymbol(QueryDatabase* db, const SymbolIdx& symbol); -std::vector GetDeclarationsOfSymbolForGotoDefinition(QueryDatabase* db, const SymbolIdx& symbol); -optional GetBaseDefinitionOrDeclarationSpelling(QueryDatabase* db, QueryFunc& func); +optional GetDeclarationFileForSymbol(QueryDatabase* db, + const SymbolIdx& symbol); +std::vector ToQueryLocation( + QueryDatabase* db, + const std::vector& refs); +std::vector ToQueryLocation(QueryDatabase* db, + const std::vector& ids); +std::vector ToQueryLocation(QueryDatabase* db, + const std::vector& ids); +std::vector ToQueryLocation(QueryDatabase* db, + const std::vector& ids); +std::vector GetUsesOfSymbol(QueryDatabase* db, + const SymbolIdx& symbol); +std::vector GetDeclarationsOfSymbolForGotoDefinition( + QueryDatabase* db, + const SymbolIdx& symbol); +optional GetBaseDefinitionOrDeclarationSpelling( + QueryDatabase* db, + QueryFunc& func); bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root); -std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, QueryFunc& root); -std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, QueryFunc& root); -optional GetLsPosition(WorkingFile* working_file, const Position& position); +std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, + QueryFunc& root); +std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, + QueryFunc& root); +optional GetLsPosition(WorkingFile* working_file, + const Position& position); optional GetLsRange(WorkingFile* working_file, const Range& location); -lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id, std::string* path); +lsDocumentUri GetLsDocumentUri(QueryDatabase* db, + QueryFileId file_id, + std::string* path); lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id); -optional GetLsLocation(QueryDatabase* db, WorkingFiles* working_files, const QueryLocation& location); -NonElidedVector GetLsLocations(QueryDatabase* db, WorkingFiles* working_files, const std::vector& locations); +optional GetLsLocation(QueryDatabase* db, + WorkingFiles* working_files, + const QueryLocation& location); +NonElidedVector GetLsLocations( + QueryDatabase* db, + WorkingFiles* working_files, + const std::vector& locations); // Returns a symbol. The symbol will have *NOT* have a location assigned. -optional GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, SymbolIdx symbol); +optional GetSymbolInfo(QueryDatabase* db, + WorkingFiles* working_files, + SymbolIdx symbol); struct CommonCodeLensParams { std::vector* result; @@ -40,21 +68,43 @@ struct CommonCodeLensParams { WorkingFile* working_file; }; -void AddCodeLens( - const char* singular, - const char* plural, - CommonCodeLensParams* common, - QueryLocation loc, - const std::vector& uses, - optional excluded, - bool force_display); +void AddCodeLens(const char* singular, + const char* plural, + CommonCodeLensParams* common, + QueryLocation loc, + const std::vector& uses, + optional excluded, + bool force_display); -lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, WorkingFiles* working_files, const std::vector& locations, const std::string& new_text); +lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, + WorkingFiles* working_files, + const std::vector& locations, + const std::string& new_text); -std::vector FindSymbolsAtLocation(WorkingFile* working_file, QueryFile* file, lsPosition position); -NonElidedVector BuildParentInheritanceHierarchyForType(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root); -optional BuildInheritanceHierarchyForType(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root_id); -NonElidedVector BuildParentInheritanceHierarchyForFunc(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root); -optional BuildInheritanceHierarchyForFunc(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root_id); -NonElidedVector BuildInitialCallTree(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root); -NonElidedVector BuildExpandCallTree(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root); \ No newline at end of file +std::vector FindSymbolsAtLocation(WorkingFile* working_file, + QueryFile* file, + lsPosition position); +NonElidedVector +BuildParentInheritanceHierarchyForType(QueryDatabase* db, + WorkingFiles* working_files, + QueryTypeId root); +optional +BuildInheritanceHierarchyForType(QueryDatabase* db, + WorkingFiles* working_files, + QueryTypeId root_id); +NonElidedVector +BuildParentInheritanceHierarchyForFunc(QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root); +optional +BuildInheritanceHierarchyForFunc(QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root_id); +NonElidedVector BuildInitialCallTree( + QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root); +NonElidedVector BuildExpandCallTree( + QueryDatabase* db, + WorkingFiles* working_files, + QueryFuncId root); \ No newline at end of file diff --git a/src/serializer.cc b/src/serializer.cc index 5c361e8b..b573cbcf 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -49,7 +49,6 @@ void Reflect(Writer& visitor, std::string& value) { visitor.String(value.c_str(), (rapidjson::SizeType)value.size()); } - // ReflectMember void ReflectMember(Writer& visitor, const char* name, std::string& value) { if (value.empty()) @@ -58,20 +57,9 @@ void ReflectMember(Writer& visitor, const char* name, std::string& value) { Reflect(visitor, value); } - - - - - - - - - - - // TODO: Move this to indexer.cc -template +template void Reflect(TVisitor& visitor, IndexType& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER2("id", value.id); @@ -91,8 +79,7 @@ void Reflect(TVisitor& visitor, IndexType& value) { REFLECT_MEMBER_END(); } - -template +template void Reflect(TVisitor& visitor, IndexFunc& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER2("id", value.id); @@ -111,8 +98,7 @@ void Reflect(TVisitor& visitor, IndexFunc& value) { REFLECT_MEMBER_END(); } - -template +template void Reflect(TVisitor& visitor, IndexVar& value) { REFLECT_MEMBER_START(); REFLECT_MEMBER2("id", value.id); @@ -130,7 +116,6 @@ void Reflect(TVisitor& visitor, IndexVar& value) { REFLECT_MEMBER_END(); } - // IndexFile bool ReflectMemberStart(Writer& visitor, IndexFile& value) { auto it = value.id_cache.usr_to_type_id.find(""); @@ -143,7 +128,7 @@ bool ReflectMemberStart(Writer& visitor, IndexFile& value) { DefaultReflectMemberStart(visitor); return true; } -template +template void Reflect(TVisitor& visitor, IndexFile& value) { REFLECT_MEMBER_START(); if (!gTestOutputMode) { @@ -161,18 +146,12 @@ void Reflect(TVisitor& visitor, IndexFile& value) { REFLECT_MEMBER_END(); } - - - - - - std::string Serialize(IndexFile& file) { rapidjson::StringBuffer output; rapidjson::PrettyWriter writer(output); - //Writer writer(output); + // Writer writer(output); writer.SetFormatOptions( - rapidjson::PrettyFormatOptions::kFormatSingleLineArray); + rapidjson::PrettyFormatOptions::kFormatSingleLineArray); writer.SetIndent(' ', 2); Reflect(writer, file); @@ -180,7 +159,9 @@ std::string Serialize(IndexFile& file) { return output.GetString(); } -std::unique_ptr Deserialize(std::string path, std::string serialized, optional expected_version) { +std::unique_ptr Deserialize(std::string path, + std::string serialized, + optional expected_version) { rapidjson::Document reader; reader.Parse(serialized.c_str()); if (reader.HasParseError()) diff --git a/src/serializer.h b/src/serializer.h index 79c2f68e..cd2699de 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -9,84 +9,63 @@ #include #include - -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; using Reader = rapidjson::GenericValue>; using Writer = rapidjson::Writer; struct IndexFile; -#define REFLECT_MEMBER_START() \ - if (!ReflectMemberStart(visitor, value)) return -#define REFLECT_MEMBER_START1(value) \ - if (!ReflectMemberStart(visitor, value)) return -#define REFLECT_MEMBER_END() \ - ReflectMemberEnd(visitor, value); -#define REFLECT_MEMBER_END1(value) \ - ReflectMemberEnd(visitor, value); -#define REFLECT_MEMBER(name) \ - ReflectMember(visitor, #name, value.name) -#define REFLECT_MEMBER2(name, value) \ - ReflectMember(visitor, name, value) +#define REFLECT_MEMBER_START() \ + if (!ReflectMemberStart(visitor, value)) \ + return +#define REFLECT_MEMBER_START1(value) \ + if (!ReflectMemberStart(visitor, value)) \ + return +#define REFLECT_MEMBER_END() ReflectMemberEnd(visitor, value); +#define REFLECT_MEMBER_END1(value) ReflectMemberEnd(visitor, value); +#define REFLECT_MEMBER(name) ReflectMember(visitor, #name, value.name) +#define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value) - -#define MAKE_REFLECT_TYPE_PROXY(type, as_type) \ - template \ +#define MAKE_REFLECT_TYPE_PROXY(type, as_type) \ + template \ void Reflect(TVisitor& visitor, type& value) { \ - auto value0 = static_cast(value); \ - Reflect(visitor, value0); \ - value = static_cast(value0); \ + auto value0 = static_cast(value); \ + Reflect(visitor, value0); \ + value = static_cast(value0); \ } -#define _MAPPABLE_REFLECT_MEMBER(name) \ - REFLECT_MEMBER(name); +#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name); -#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \ - template \ +#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \ + template \ void Reflect(TVisitor& visitor, type& value) { \ - REFLECT_MEMBER_START(); \ - REFLECT_MEMBER_END(); \ + REFLECT_MEMBER_START(); \ + REFLECT_MEMBER_END(); \ } -#define MAKE_REFLECT_STRUCT(type, ...) \ - template \ - void Reflect(TVisitor& visitor, type& value) { \ - REFLECT_MEMBER_START(); \ +#define MAKE_REFLECT_STRUCT(type, ...) \ + template \ + void Reflect(TVisitor& visitor, type& value) { \ + REFLECT_MEMBER_START(); \ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \ - REFLECT_MEMBER_END(); \ + REFLECT_MEMBER_END(); \ } -#define _MAPPABLE_REFLECT_ARRAY(name) \ - Reflect(visitor, value.name); +#define _MAPPABLE_REFLECT_ARRAY(name) Reflect(visitor, value.name); // Reflects the struct so it is serialized as an array instead of an object. // This currently only supports writers. #define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \ - inline void Reflect(Writer& visitor, type& value) { \ - visitor.StartArray(); \ - MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \ - visitor.EndArray(); \ + inline void Reflect(Writer& visitor, type& value) { \ + visitor.StartArray(); \ + MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \ + visitor.EndArray(); \ } - - - - - - -template +template struct NonElidedVector : public std::vector {}; - - - - - - - - - // API: /* template @@ -108,7 +87,6 @@ void ReflectMemberEnd(TVisitor& visitor, T& value) { } */ - // int16_t void Reflect(Reader& visitor, int16_t& value); void Reflect(Writer& visitor, int16_t& value); @@ -128,21 +106,15 @@ void Reflect(Writer& visitor, bool& value); void Reflect(Reader& visitor, std::string& value); void Reflect(Writer& visitor, std::string& value); - - - - - - // Writer: -template +template void Reflect(Writer& visitor, std::vector& values) { visitor.StartArray(); for (auto& value : values) Reflect(visitor, value); visitor.EndArray(); } -template +template void Reflect(Writer& visitor, optional value) { if (value) Reflect(visitor, value.value()); @@ -150,21 +122,21 @@ void Reflect(Writer& visitor, optional value) { inline void DefaultReflectMemberStart(Writer& visitor) { visitor.StartObject(); } -template +template bool ReflectMemberStart(Writer& visitor, T& value) { visitor.StartObject(); return true; } -template +template void ReflectMemberEnd(Writer& visitor, T& value) { visitor.EndObject(); } -template +template void ReflectMember(Writer& visitor, const char* name, T& value) { visitor.Key(name); Reflect(visitor, value); } -template +template void ReflectMember(Writer& visitor, const char* name, std::vector& values) { if (values.empty()) return; @@ -174,15 +146,17 @@ void ReflectMember(Writer& visitor, const char* name, std::vector& values) { Reflect(visitor, value); visitor.EndArray(); } -template -void ReflectMember(Writer& visitor, const char* name, NonElidedVector& values) { +template +void ReflectMember(Writer& visitor, + const char* name, + NonElidedVector& values) { visitor.Key(name); visitor.StartArray(); for (auto& value : values) Reflect(visitor, value); visitor.EndArray(); } -template +template void ReflectMember(Writer& visitor, const char* name, optional& value) { if (!value) return; @@ -192,7 +166,7 @@ void ReflectMember(Writer& visitor, const char* name, optional& value) { void ReflectMember(Writer& visitor, const char* name, std::string& value); // Reader: -template +template void Reflect(Reader& visitor, std::vector& values) { for (auto& entry : visitor.GetArray()) { T entry_value; @@ -200,20 +174,20 @@ void Reflect(Reader& visitor, std::vector& values) { values.push_back(entry_value); } } -template +template void Reflect(Reader& visitor, optional& value) { T real_value; Reflect(visitor, real_value); value = real_value; } inline void DefaultReflectMemberStart(Reader& visitor) {} -template +template bool ReflectMemberStart(Reader& visitor, T& value) { return true; } -template +template void ReflectMemberEnd(Reader& visitor, T& value) {} -template +template void ReflectMember(Reader& visitor, const char* name, T& value) { auto it = visitor.FindMember(name); if (it != visitor.MemberEnd()) { @@ -223,6 +197,8 @@ void ReflectMember(Reader& visitor, const char* name, T& value) { } std::string Serialize(IndexFile& file); -std::unique_ptr Deserialize(std::string path, std::string serialized, optional expected_version); +std::unique_ptr Deserialize(std::string path, + std::string serialized, + optional expected_version); void SetTestOutputMode(); diff --git a/src/standard_includes.cc b/src/standard_includes.cc index cda94b42..42cc35b3 100644 --- a/src/standard_includes.cc +++ b/src/standard_includes.cc @@ -2,181 +2,181 @@ // See http://stackoverflow.com/a/2029106. const char* kStandardLibraryIncludes[177] = { - "aio.h", - "algorithm", - "any", - "arpa/inet.h", - "array", - "assert.h", - "atomic", - "bitset", - "cassert", - "ccomplex", - "cctype", - "cerrno", - "cfenv", - "cfloat", - "chrono", - "cinttypes", - "ciso646", - "climits", - "clocale", - "cmath", - "codecvt", - "complex", - "complex.h", - "condition_variable", - "cpio.h", - "csetjmp", - "csignal", - "cstdalign", - "cstdarg", - "cstdbool", - "cstddef", - "cstdint", - "cstdio", - "cstdlib", - "cstring", - "ctgmath", - "ctime", - "ctype.h", - "cuchar", - "curses.h", - "cwchar", - "cwctype", - "deque", - "dirent.h", - "dlfcn.h", - "errno.h", - "exception", - "execution", - "fcntl.h", - "fenv.h", - "filesystem", - "float.h", - "fmtmsg.h", - "fnmatch.h", - "forward_list", - "fstream", - "ftw.h", - "functional", - "future", - "glob.h", - "grp.h", - "iconv.h", - "initializer_list", - "inttypes.h", - "iomanip", - "ios", - "iosfwd", - "iostream", - "iso646.h", - "istream", - "iterator", - "langinfo.h", - "libgen.h", - "limits", - "limits.h", - "list", - "locale", - "locale.h", - "map", - "math.h", - "memory", - "memory_resource", - "monetary.h", - "mqueue.h", - "mutex", - "ndbm.h", - "net/if.h", - "netdb.h", - "netinet/in.h", - "netinet/tcp.h", - "new", - "nl_types.h", - "numeric", - "optional", - "ostream", - "poll.h", - "pthread.h", - "pwd.h", - "queue", - "random", - "ratio", - "regex", - "regex.h", - "sched.h", - "scoped_allocator", - "search.h", - "semaphore.h", - "set", - "setjmp.h", - "shared_mutex", - "signal.h", - "spawn.h", - "sstream", - "stack", - "stdalign.h", - "stdarg.h", - "stdatomic.h", - "stdbool.h", - "stddef.h", - "stdexcept", - "stdint.h", - "stdio.h", - "stdlib.h", - "stdnoreturn.h", - "streambuf", - "string", - "string.h", - "string_view", - "strings.h", - "stropts.h", - "strstream", - "sys/ipc.h", - "sys/mman.h", - "sys/msg.h", - "sys/resource.h", - "sys/select.h", - "sys/sem.h", - "sys/shm.h", - "sys/socket.h", - "sys/stat.h", - "sys/statvfs.h", - "sys/time.h", - "sys/times.h", - "sys/types.h", - "sys/uio.h", - "sys/un.h", - "sys/utsname.h", - "sys/wait.h", - "syslog.h", - "system_error", - "tar.h", - "term.h", - "termios.h", - "tgmath.h", - "thread", - "threads.h", - "time.h", - "trace.h", - "tuple", - "type_traits", - "typeindex", - "typeinfo", - "uchar.h", - "ulimit.h", - "uncntrl.h", - "unistd.h", - "unordered_map", - "unordered_set", - "utility", - "utime.h", - "utmpx.h", - "valarray", - "variant", - "vector", - "wchar.h", - "wctype.h", - "wordexp.h", + "aio.h", + "algorithm", + "any", + "arpa/inet.h", + "array", + "assert.h", + "atomic", + "bitset", + "cassert", + "ccomplex", + "cctype", + "cerrno", + "cfenv", + "cfloat", + "chrono", + "cinttypes", + "ciso646", + "climits", + "clocale", + "cmath", + "codecvt", + "complex", + "complex.h", + "condition_variable", + "cpio.h", + "csetjmp", + "csignal", + "cstdalign", + "cstdarg", + "cstdbool", + "cstddef", + "cstdint", + "cstdio", + "cstdlib", + "cstring", + "ctgmath", + "ctime", + "ctype.h", + "cuchar", + "curses.h", + "cwchar", + "cwctype", + "deque", + "dirent.h", + "dlfcn.h", + "errno.h", + "exception", + "execution", + "fcntl.h", + "fenv.h", + "filesystem", + "float.h", + "fmtmsg.h", + "fnmatch.h", + "forward_list", + "fstream", + "ftw.h", + "functional", + "future", + "glob.h", + "grp.h", + "iconv.h", + "initializer_list", + "inttypes.h", + "iomanip", + "ios", + "iosfwd", + "iostream", + "iso646.h", + "istream", + "iterator", + "langinfo.h", + "libgen.h", + "limits", + "limits.h", + "list", + "locale", + "locale.h", + "map", + "math.h", + "memory", + "memory_resource", + "monetary.h", + "mqueue.h", + "mutex", + "ndbm.h", + "net/if.h", + "netdb.h", + "netinet/in.h", + "netinet/tcp.h", + "new", + "nl_types.h", + "numeric", + "optional", + "ostream", + "poll.h", + "pthread.h", + "pwd.h", + "queue", + "random", + "ratio", + "regex", + "regex.h", + "sched.h", + "scoped_allocator", + "search.h", + "semaphore.h", + "set", + "setjmp.h", + "shared_mutex", + "signal.h", + "spawn.h", + "sstream", + "stack", + "stdalign.h", + "stdarg.h", + "stdatomic.h", + "stdbool.h", + "stddef.h", + "stdexcept", + "stdint.h", + "stdio.h", + "stdlib.h", + "stdnoreturn.h", + "streambuf", + "string", + "string.h", + "string_view", + "strings.h", + "stropts.h", + "strstream", + "sys/ipc.h", + "sys/mman.h", + "sys/msg.h", + "sys/resource.h", + "sys/select.h", + "sys/sem.h", + "sys/shm.h", + "sys/socket.h", + "sys/stat.h", + "sys/statvfs.h", + "sys/time.h", + "sys/times.h", + "sys/types.h", + "sys/uio.h", + "sys/un.h", + "sys/utsname.h", + "sys/wait.h", + "syslog.h", + "system_error", + "tar.h", + "term.h", + "termios.h", + "tgmath.h", + "thread", + "threads.h", + "time.h", + "trace.h", + "tuple", + "type_traits", + "typeindex", + "typeinfo", + "uchar.h", + "ulimit.h", + "uncntrl.h", + "unistd.h", + "unordered_map", + "unordered_set", + "utility", + "utime.h", + "utmpx.h", + "valarray", + "variant", + "vector", + "wchar.h", + "wctype.h", + "wordexp.h", }; \ No newline at end of file diff --git a/src/test.cc b/src/test.cc index 679f8c00..40344380 100644 --- a/src/test.cc +++ b/src/test.cc @@ -14,7 +14,7 @@ std::string ToString(const rapidjson::Document& document) { rapidjson::StringBuffer buffer; rapidjson::PrettyWriter writer(buffer); writer.SetFormatOptions( - rapidjson::PrettyFormatOptions::kFormatSingleLineArray); + rapidjson::PrettyFormatOptions::kFormatSingleLineArray); writer.SetIndent(' ', 2); buffer.Clear(); @@ -22,16 +22,24 @@ std::string ToString(const rapidjson::Document& document) { return buffer.GetString(); } -void DiffDocuments(std::string path, std::string path_section, rapidjson::Document& expected, rapidjson::Document& actual) { +void DiffDocuments(std::string path, + std::string path_section, + rapidjson::Document& expected, + rapidjson::Document& actual) { std::string joined_actual_output = ToString(actual); - std::vector actual_output = SplitString(joined_actual_output, "\n"); + std::vector actual_output = + SplitString(joined_actual_output, "\n"); std::string joined_expected_output = ToString(expected); - std::vector expected_output = SplitString(joined_expected_output, "\n"); + std::vector expected_output = + SplitString(joined_expected_output, "\n"); - std::cout << "[FAILED] " << path << " (section " << path_section << ")" << std::endl; - std::cout << "Expected output for " << path << " (section " << path_section << "):" << std::endl; + std::cout << "[FAILED] " << path << " (section " << path_section << ")" + << std::endl; + std::cout << "Expected output for " << path << " (section " << path_section + << "):" << std::endl; std::cout << joined_expected_output << std::endl; - std::cout << "Actual output for " << path << " (section " << path_section << "):" << std::endl; + std::cout << "Actual output for " << path << " (section " << path_section + << "):" << std::endl; std::cout << joined_actual_output << std::endl; std::cout << std::endl; @@ -66,15 +74,19 @@ void DiffDocuments(std::string path, std::string path_section, rapidjson::Docume void VerifySerializeToFrom(IndexFile* file) { std::string expected = file->ToString(); - std::unique_ptr result = Deserialize("--.cc", Serialize(*file), nullopt /*expected_version*/); + std::unique_ptr result = + Deserialize("--.cc", Serialize(*file), nullopt /*expected_version*/); std::string actual = result->ToString(); if (expected != actual) { - std::cerr << "Serialization failure" << std::endl;; + std::cerr << "Serialization failure" << std::endl; + ; assert(false); } } -std::string FindExpectedOutputForFilename(std::string filename, const std::unordered_map& expected) { +std::string FindExpectedOutputForFilename( + std::string filename, + const std::unordered_map& expected) { for (const auto& entry : expected) { if (EndsWith(entry.first, filename)) return entry.second; @@ -86,7 +98,9 @@ std::string FindExpectedOutputForFilename(std::string filename, const std::unord return "{}"; } -IndexFile* FindDbForPathEnding(const std::string& path, const std::vector>& dbs) { +IndexFile* FindDbForPathEnding( + const std::string& path, + const std::vector>& dbs) { for (auto& db : dbs) { if (EndsWith(db->path, path)) return db.get(); @@ -101,48 +115,48 @@ void RunTests() { bool update_all = false; clang::Index index(1, 0); - for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) { + for (std::string path : GetFilesInFolder("tests", true /*recursive*/, + true /*add_folder_to_path*/)) { float memory_before = GetProcessMemoryUsedInMb(); float memory_after = -1.; { - //if (path != "tests/templates/specialized_func_definition.cc") continue; - //if (path != "tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc") continue; - //if (path != "tests/multi_file/funky_enum.cc") continue; - //if (path != "tests/multi_file/simple_impl.cc") continue; - //if (path != "tests/inheritance/interface_pure_virtual.cc") continue; - //if (path != "tests/_empty_test.cc") continue; - //if (path != "tests/declaration_vs_definition/func_associated_function_params.cc") continue; + // if (path != "tests/templates/specialized_func_definition.cc") continue; + // if (path != + // "tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc") + // continue; if (path != "tests/multi_file/funky_enum.cc") continue; if + // (path != "tests/multi_file/simple_impl.cc") continue; if (path != + // "tests/inheritance/interface_pure_virtual.cc") continue; if (path != + // "tests/_empty_test.cc") continue; if (path != + // "tests/declaration_vs_definition/func_associated_function_params.cc") + // continue; - //if (path != "tests/templates/template_class_type_usage_folded_into_one.cc") continue; - //path = "C:/Users/jacob/Desktop/superindex/indexer/" + path; + // if (path != + // "tests/templates/template_class_type_usage_folded_into_one.cc") + // continue; path = "C:/Users/jacob/Desktop/superindex/indexer/" + path; Config config; FileConsumer::SharedState file_consumer_shared; // Run test. - //std::cout << "[START] " << path << std::endl; + // std::cout << "[START] " << path << std::endl; PerformanceImportFile perf; std::vector> dbs = Parse( - &config, &file_consumer_shared, - path, - { - "-xc++", - "-std=c++11", - "-IC:/Users/jacob/Desktop/cquery/third_party/", - "-IC:/Users/jacob/Desktop/cquery/third_party/doctest/", - "-IC:/Users/jacob/Desktop/cquery/third_party/rapidjson/include", - "-IC:/Users/jacob/Desktop/cquery/src", - "-isystemC:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.10.25017/include", - "-isystemC:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt" - }, - {}, - &perf, - &index, - false /*dump_ast*/); + &config, &file_consumer_shared, path, + {"-xc++", "-std=c++11", + "-IC:/Users/jacob/Desktop/cquery/third_party/", + "-IC:/Users/jacob/Desktop/cquery/third_party/doctest/", + "-IC:/Users/jacob/Desktop/cquery/third_party/rapidjson/include", + "-IC:/Users/jacob/Desktop/cquery/src", + "-isystemC:/Program Files (x86)/Microsoft Visual " + "Studio/2017/Community/VC/Tools/MSVC/14.10.25017/include", + "-isystemC:/Program Files (x86)/Windows " + "Kits/10/Include/10.0.15063.0/ucrt"}, + {}, &perf, &index, false /*dump_ast*/); // Parse expected output from the test, parse it into JSON document. - std::unordered_map all_expected_output = ParseTestExpectation(path); + std::unordered_map all_expected_output = + ParseTestExpectation(path); for (auto& entry : all_expected_output) { const std::string& expected_path = entry.first; const std::string& expected_output = entry.second; @@ -164,12 +178,12 @@ void RunTests() { if (actual == expected) { std::cout << "[PASSED] " << path << std::endl; - } - else { + } else { DiffDocuments(path, expected_path, expected, actual); std::cout << std::endl; std::cout << std::endl; - std::cout << "[Enter to continue - type u to update test, a to update all]"; + std::cout + << "[Enter to continue - type u to update test, a to update all]"; char c = 'u'; if (!update_all) { c = (char)std::cin.get(); @@ -180,9 +194,9 @@ void RunTests() { update_all = true; if (update_all || c == 'u') { - UpdateTestExpectation(path, expected_output, ToString(actual) + "\n"); + UpdateTestExpectation(path, expected_output, + ToString(actual) + "\n"); } - } } @@ -190,12 +204,16 @@ void RunTests() { } float memory_cleanup = GetProcessMemoryUsedInMb(); - std::cerr << "[memory] before=" << memory_before << "mb, after=" << memory_after << "mb, cleanup=" << memory_cleanup << "mb" << std::endl; + std::cerr << "[memory] before=" << memory_before + << "mb, after=" << memory_after + << "mb, cleanup=" << memory_cleanup << "mb" << std::endl; } - std::cerr << "[final presleep] " << GetProcessMemoryUsedInMb() << "mb" << std::endl; - //std::this_thread::sleep_for(std::chrono::seconds(10)); - //std::cerr << "[final postsleep] " << GetProcessMemoryUsedInMb() << "mb" << std::endl; + std::cerr << "[final presleep] " << GetProcessMemoryUsedInMb() << "mb" + << std::endl; + // std::this_thread::sleep_for(std::chrono::seconds(10)); + // std::cerr << "[final postsleep] " << GetProcessMemoryUsedInMb() << "mb" << + // std::endl; std::cerr << std::endl; std::cerr << std::endl; std::cerr << std::endl; @@ -204,5 +222,5 @@ void RunTests() { } // TODO: ctor/dtor, copy ctor -// TODO: Always pass IndexFile by pointer, ie, search and remove all IndexFile& refs. - +// TODO: Always pass IndexFile by pointer, ie, search and remove all IndexFile& +// refs. diff --git a/src/test.h b/src/test.h index 43a0ead1..625ebf50 100644 --- a/src/test.h +++ b/src/test.h @@ -1,3 +1,3 @@ #pragma once - + void RunTests(); \ No newline at end of file diff --git a/src/threaded_queue.h b/src/threaded_queue.h index 89022e63..d1465c15 100644 --- a/src/threaded_queue.h +++ b/src/threaded_queue.h @@ -1,16 +1,18 @@ #pragma once -#include "work_thread.h" #include +#include "work_thread.h" + #include #include -#include -#include #include +#include +#include + -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; // TODO: cleanup includes. @@ -56,7 +58,7 @@ struct MultiQueueWaiter { // A threadsafe-queue. http://stackoverflow.com/a/16075550 template struct ThreadedQueue : public BaseThreadQueue { -public: + public: ThreadedQueue() { owned_waiter_ = MakeUnique(); waiter_ = owned_waiter_.get(); @@ -111,12 +113,11 @@ public: // Get the first element from the queue. Blocks until one is available. // Executes |action| with an acquired |mutex_|. - template + template T DequeuePlusAction(TAction action) { std::unique_lock lock(mutex_); - waiter_->cv.wait(lock, [&]() { - return !priority_.empty() || !queue_.empty(); - }); + waiter_->cv.wait(lock, + [&]() { return !priority_.empty() || !queue_.empty(); }); if (!priority_.empty()) { auto val = std::move(priority_.front()); @@ -139,7 +140,7 @@ public: // Get the first element from the queue without blocking. Returns a null // value if the queue is empty. - template + template optional TryDequeuePlusAction(TAction action) { std::lock_guard lock(mutex_); if (priority_.empty() && queue_.empty()) diff --git a/src/timer.cc b/src/timer.cc index b74871ad..1c93b28c 100644 --- a/src/timer.cc +++ b/src/timer.cc @@ -10,12 +10,15 @@ Timer::Timer() { long long Timer::ElapsedMicroseconds() const { std::chrono::time_point end = Clock::now(); - return std::chrono::duration_cast(end - start).count(); + return std::chrono::duration_cast(end - start) + .count(); } long long Timer::ElapsedMicrosecondsAndReset() { std::chrono::time_point end = Clock::now(); - long long microseconds = std::chrono::duration_cast(end - start).count(); + long long microseconds = + std::chrono::duration_cast(end - start) + .count(); Reset(); return microseconds; } @@ -26,11 +29,14 @@ void Timer::Reset() { void Timer::ResetAndPrint(const std::string& message) { std::chrono::time_point end = Clock::now(); - long long elapsed = std::chrono::duration_cast(end - start).count(); + long long elapsed = + std::chrono::duration_cast(end - start) + .count(); long long milliseconds = elapsed / 1000; long long remaining = elapsed - milliseconds; - LOG_S(INFO) << message << " took " << milliseconds << "." << remaining << "ms"; + LOG_S(INFO) << message << " took " << milliseconds << "." << remaining + << "ms"; Reset(); } \ No newline at end of file diff --git a/src/typed_bidi_message_queue.h b/src/typed_bidi_message_queue.h index cc524534..e5538871 100644 --- a/src/typed_bidi_message_queue.h +++ b/src/typed_bidi_message_queue.h @@ -17,12 +17,10 @@ struct TypedBidiMessageQueue { std::function(Reader& visitor)>; TypedBidiMessageQueue(const std::string& name, size_t buffer_size) - : for_server( - Buffer::CreateSharedBuffer(name + "_fs", buffer_size), - false /*buffer_has_data*/), - for_client( - Buffer::CreateSharedBuffer(name + "_fc", buffer_size), - true /*buffer_has_data*/) {} + : for_server(Buffer::CreateSharedBuffer(name + "_fs", buffer_size), + false /*buffer_has_data*/), + for_client(Buffer::CreateSharedBuffer(name + "_fc", buffer_size), + true /*buffer_has_data*/) {} void RegisterId(TId id, const Serializer& serializer, @@ -42,7 +40,8 @@ struct TypedBidiMessageQueue { writer.SetIndent(' ', 0); // Serialize the message. - assert(serializers_.find(id) != serializers_.end() && "No registered serializer"); + assert(serializers_.find(id) != serializers_.end() && + "No registered serializer"); const Serializer& serializer = serializers_.find(id)->second; serializer(writer, message); diff --git a/src/utils.cc b/src/utils.cc index 71570df1..a26188d1 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -7,25 +7,29 @@ #include #include #include +#include #include #include -#include #include #include #include + #if !defined(__APPLE__) #include #endif // See http://stackoverflow.com/a/217605 void TrimStart(std::string& s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), - std::not1(std::ptr_fun(std::isspace)))); + s.erase(s.begin(), + std::find_if(s.begin(), s.end(), + std::not1(std::ptr_fun(std::isspace)))); } void TrimEnd(std::string& s) { s.erase(std::find_if(s.rbegin(), s.rend(), - std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + std::not1(std::ptr_fun(std::isspace))) + .base(), + s.end()); } void Trim(std::string& s) { TrimStart(s); @@ -45,20 +49,24 @@ bool StartsWith(const std::string& value, const std::string& start) { return std::equal(start.begin(), start.end(), value.begin()); } -bool AnyStartsWith(const std::vector& values, const std::string& start) { - return std::any_of(std::begin(values), std::end(values), [&start](const std::string& value) { - return StartsWith(value, start); - }); +bool AnyStartsWith(const std::vector& values, + const std::string& start) { + return std::any_of( + std::begin(values), std::end(values), + [&start](const std::string& value) { return StartsWith(value, start); }); } -bool EndsWithAny(const std::string& value, const std::vector& endings) { - return std::any_of(std::begin(endings), std::end(endings), [&value](const std::string& ending) { - return EndsWith(value, ending); - }); +bool EndsWithAny(const std::string& value, + const std::vector& endings) { + return std::any_of( + std::begin(endings), std::end(endings), + [&value](const std::string& ending) { return EndsWith(value, ending); }); } // See http://stackoverflow.com/a/29752943 -std::string ReplaceAll(const std::string& source, const std::string& from, const std::string& to) { +std::string ReplaceAll(const std::string& source, + const std::string& from, + const std::string& to) { std::string result; result.reserve(source.length()); // avoids a few memory allocations @@ -77,7 +85,8 @@ std::string ReplaceAll(const std::string& source, const std::string& from, const return result; } -std::vector SplitString(const std::string& str, const std::string& delimiter) { +std::vector SplitString(const std::string& str, + const std::string& delimiter) { // http://stackoverflow.com/a/13172514 std::vector strings; @@ -104,17 +113,20 @@ std::string LowerPathIfCaseInsensitive(const std::string& path) { } static void GetFilesInFolderHelper( - std::string folder, bool recursive, std::string output_prefix, const std::function& handler) { + std::string folder, + bool recursive, + std::string output_prefix, + const std::function& handler) { tinydir_dir dir; if (tinydir_open(&dir, folder.c_str()) == -1) { - //perror("Error opening file"); + // perror("Error opening file"); goto bail; } while (dir.has_next) { tinydir_file file; if (tinydir_readfile(&dir, &file) == -1) { - //perror("Error getting file"); + // perror("Error getting file"); goto bail; } @@ -127,10 +139,10 @@ static void GetFilesInFolderHelper( if (recursive) { std::string child_dir = output_prefix + file.name + "/"; if (!IsSymLink(child_dir)) - GetFilesInFolderHelper(file.path, true /*recursive*/, child_dir, handler); + GetFilesInFolderHelper(file.path, true /*recursive*/, child_dir, + handler); } - } - else { + } else { handler(output_prefix + file.name); } } @@ -145,19 +157,24 @@ bail: tinydir_close(&dir); } -std::vector GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path) { +std::vector GetFilesInFolder(std::string folder, + bool recursive, + bool add_folder_to_path) { EnsureEndsInSlash(folder); std::vector result; - GetFilesInFolderHelper(folder, recursive, add_folder_to_path ? folder : "", [&result](const std::string& path) { - result.push_back(path); - }); + GetFilesInFolderHelper( + folder, recursive, add_folder_to_path ? folder : "", + [&result](const std::string& path) { result.push_back(path); }); return result; } - -void GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path, const std::function& handler) { +void GetFilesInFolder(std::string folder, + bool recursive, + bool add_folder_to_path, + const std::function& handler) { EnsureEndsInSlash(folder); - GetFilesInFolderHelper(folder, recursive, add_folder_to_path ? folder : "", handler); + GetFilesInFolderHelper(folder, recursive, add_folder_to_path ? folder : "", + handler); } void EnsureEndsInSlash(std::string& path) { @@ -165,38 +182,37 @@ void EnsureEndsInSlash(std::string& path) { path += '/'; } - // http://stackoverflow.com/a/6089413 std::istream& SafeGetline(std::istream& is, std::string& t) { - t.clear(); + t.clear(); - // The characters in the stream are read one-by-one using a std::streambuf. - // That is faster than reading them one-by-one using the std::istream. - // Code that uses streambuf this way must be guarded by a sentry object. - // The sentry object performs various tasks, - // such as thread synchronization and updating the stream state. + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. - std::istream::sentry se(is, true); - std::streambuf* sb = is.rdbuf(); + std::istream::sentry se(is, true); + std::streambuf* sb = is.rdbuf(); - for(;;) { - int c = sb->sbumpc(); - switch (c) { - case '\n': - return is; - case '\r': - if(sb->sgetc() == '\n') - sb->sbumpc(); - return is; - case EOF: - // Also handle the case when the last line has no line ending - if(t.empty()) - is.setstate(std::ios::eofbit); - return is; - default: - t += (char)c; - } + for (;;) { + int c = sb->sbumpc(); + switch (c) { + case '\n': + return is; + case '\r': + if (sb->sgetc() == '\n') + sb->sbumpc(); + return is; + case EOF: + // Also handle the case when the last line has no line ending + if (t.empty()) + is.setstate(std::ios::eofbit); + return is; + default: + t += (char)c; } + } } optional ReadContent(const std::string& filename) { @@ -205,22 +221,22 @@ optional ReadContent(const std::string& filename) { if (!cache.good()) return nullopt; - return std::string( - std::istreambuf_iterator(cache), - std::istreambuf_iterator()); + return std::string(std::istreambuf_iterator(cache), + std::istreambuf_iterator()); } std::vector ReadLines(std::string filename) { std::vector result; std::ifstream input(filename); - for (std::string line; SafeGetline(input, line); ) + for (std::string line; SafeGetline(input, line);) result.push_back(line); return result; } -std::vector ToLines(const std::string& content, bool trim_whitespace) { +std::vector ToLines(const std::string& content, + bool trim_whitespace) { std::vector result; std::istringstream lines(content); @@ -235,11 +251,12 @@ std::vector ToLines(const std::string& content, bool trim_whitespac return result; } -std::unordered_map ParseTestExpectation(std::string filename) { +std::unordered_map ParseTestExpectation( + std::string filename) { bool in_output = false; #if false - #include "bar.h" +#include "bar.h" void foo(); @@ -275,8 +292,7 @@ std::unordered_map ParseTestExpectation(std::string fi active_output_contents = ""; in_output = true; - } - else if (in_output) + } else if (in_output) active_output_contents += line + "\n"; } @@ -285,11 +301,14 @@ std::unordered_map ParseTestExpectation(std::string fi return result; } -void UpdateTestExpectation(const std::string& filename, const std::string& expectation, const std::string& actual) { +void UpdateTestExpectation(const std::string& filename, + const std::string& expectation, + const std::string& actual) { // Read the entire file into a string. std::ifstream in(filename); std::string str; - str.assign(std::istreambuf_iterator(in), std::istreambuf_iterator()); + str.assign(std::istreambuf_iterator(in), + std::istreambuf_iterator()); in.close(); // Replace expectation @@ -333,4 +352,3 @@ std::string FormatMicroseconds(long long microseconds) { return std::to_string(milliseconds) + "." + std::to_string(remaining) + "ms"; } - diff --git a/src/utils.h b/src/utils.h index 23b722e5..2c810954 100644 --- a/src/utils.h +++ b/src/utils.h @@ -10,8 +10,8 @@ #include #include -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; // Trim from start (in place) void TrimStart(std::string& s); @@ -23,16 +23,20 @@ void Trim(std::string& s); // Returns true if |value| starts/ends with |start| or |ending|. bool StartsWith(const std::string& value, const std::string& start); bool EndsWith(const std::string& value, const std::string& ending); -bool AnyStartsWith(const std::vector& values, const std::string& start); -bool EndsWithAny(const std::string& value, const std::vector& endings); +bool AnyStartsWith(const std::vector& values, + const std::string& start); +bool EndsWithAny(const std::string& value, + const std::vector& endings); -std::string ReplaceAll(const std::string& source, const std::string& from, const std::string& to); +std::string ReplaceAll(const std::string& source, + const std::string& from, + const std::string& to); -std::vector SplitString(const std::string& str, const std::string& delimiter); +std::vector SplitString(const std::string& str, + const std::string& delimiter); std::string LowerPathIfCaseInsensitive(const std::string& path); - template std::string StringJoinMap(const TValues& values, const TMap& map) { std::string result; @@ -48,56 +52,66 @@ std::string StringJoinMap(const TValues& values, const TMap& map) { template std::string StringJoin(const TValues& values) { - return StringJoinMap(values, [](const std::string& entry) { - return entry; - }); + return StringJoinMap(values, [](const std::string& entry) { return entry; }); } // Finds all files in the given folder. This is recursive. -std::vector GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path); -void GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path, const std::function& handler); +std::vector GetFilesInFolder(std::string folder, + bool recursive, + bool add_folder_to_path); +void GetFilesInFolder(std::string folder, + bool recursive, + bool add_folder_to_path, + const std::function& handler); // Ensures that |path| ends in a slash. void EnsureEndsInSlash(std::string& path); optional ReadContent(const std::string& filename); std::vector ReadLines(std::string filename); -std::vector ToLines(const std::string& content, bool trim_whitespace); +std::vector ToLines(const std::string& content, + bool trim_whitespace); - -std::unordered_map ParseTestExpectation(std::string filename); -void UpdateTestExpectation(const std::string& filename, const std::string& expectation, const std::string& actual); +std::unordered_map ParseTestExpectation( + std::string filename); +void UpdateTestExpectation(const std::string& filename, + const std::string& expectation, + const std::string& actual); void Fail(const std::string& message); - void WriteToFile(const std::string& filename, const std::string& content); // note: this implementation does not disable this overload for array types -// See http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique#Possible_Implementatiog -template +// See +// http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique#Possible_Implementatiog +template std::unique_ptr MakeUnique(Args&&... args) { - return std::unique_ptr(new T(std::forward(args)...)); + return std::unique_ptr(new T(std::forward(args)...)); } -template +template void AddRange(std::vector* dest, const std::vector& to_add) { for (const T& e : to_add) dest->push_back(e); } -template +template void PushRange(std::queue* dest, const std::vector& to_add) { for (const T& e : to_add) dest->push(e); } -template +template void RemoveRange(std::vector* dest, const std::vector& to_remove) { - dest->erase(std::remove_if(dest->begin(), dest->end(), [&](const T& t) { - // TODO: make to_remove a set? - return std::find(to_remove.begin(), to_remove.end(), t) != to_remove.end(); - }), dest->end()); + dest->erase(std::remove_if(dest->begin(), dest->end(), + [&](const T& t) { + // TODO: make to_remove a set? + return std::find(to_remove.begin(), + to_remove.end(), + t) != to_remove.end(); + }), + dest->end()); } // http://stackoverflow.com/a/38140932 @@ -109,7 +123,7 @@ void RemoveRange(std::vector* dest, const std::vector& to_remove) { // }; // MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3) -inline void hash_combine(std::size_t& seed) { } +inline void hash_combine(std::size_t& seed) {} template inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) { @@ -118,25 +132,27 @@ inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) { hash_combine(seed, rest...); } -#define MAKE_HASHABLE(type, ...) \ - namespace std {\ - template<> struct hash {\ - std::size_t operator()(const type &t) const {\ - std::size_t ret = 0;\ - hash_combine(ret, __VA_ARGS__);\ - return ret;\ - }\ - };\ - } +#define MAKE_HASHABLE(type, ...) \ + namespace std { \ + template <> \ + struct hash { \ + std::size_t operator()(const type& t) const { \ + std::size_t ret = 0; \ + hash_combine(ret, __VA_ARGS__); \ + return ret; \ + } \ + }; \ + } -#define MAKE_ENUM_HASHABLE(type) \ - namespace std {\ - template<> struct hash {\ - std::size_t operator()(const type &t) const {\ - return hash()(static_cast(t));\ - }\ - };\ - } +#define MAKE_ENUM_HASHABLE(type) \ + namespace std { \ + template <> \ + struct hash { \ + std::size_t operator()(const type& t) const { \ + return hash()(static_cast(t)); \ + } \ + }; \ + } float GetProcessMemoryUsedInMb(); diff --git a/src/work_thread.cc b/src/work_thread.cc index f6b905b4..79d4853c 100644 --- a/src/work_thread.cc +++ b/src/work_thread.cc @@ -6,9 +6,8 @@ std::atomic WorkThread::num_active_threads; std::atomic WorkThread::request_exit_on_idle; // static -void WorkThread::StartThread( - const std::string& thread_name, - const std::function& entry_point) { +void WorkThread::StartThread(const std::string& thread_name, + const std::function& entry_point) { new std::thread([thread_name, entry_point]() { SetCurrentThreadName(thread_name); diff --git a/src/work_thread.h b/src/work_thread.h index 6a80c547..27350317 100644 --- a/src/work_thread.h +++ b/src/work_thread.h @@ -9,11 +9,7 @@ // Helper methods for starting threads that do some work. Enables test code to // wait for all work to complete. struct WorkThread { - enum class Result { - MoreWork, - NoWork, - ExitThread - }; + enum class Result { MoreWork, NoWork, ExitThread }; // The number of active worker threads. static std::atomic num_active_threads; @@ -22,9 +18,8 @@ struct WorkThread { // Launch a new thread. |entry_point| will be called continously. It should // return true if it there is still known work to be done. - static void StartThread( - const std::string& thread_name, - const std::function& entry_point); + static void StartThread(const std::string& thread_name, + const std::function& entry_point); // Static-only class. WorkThread() = delete; diff --git a/src/working_files.cc b/src/working_files.cc index 736c747a..bc198ee4 100644 --- a/src/working_files.cc +++ b/src/working_files.cc @@ -19,8 +19,7 @@ lsPosition GetPositionForOffset(const std::string& content, int offset) { if (content[i] == '\n') { result.line += 1; result.character = 0; - } - else { + } else { result.character += 1; } ++i; @@ -31,9 +30,8 @@ lsPosition GetPositionForOffset(const std::string& content, int offset) { } // namespace - - -WorkingFile::WorkingFile(const std::string& filename, const std::string& buffer_content) +WorkingFile::WorkingFile(const std::string& filename, + const std::string& buffer_content) : filename(filename), buffer_content(buffer_content) { OnBufferContentUpdated(); @@ -51,7 +49,7 @@ void WorkingFile::SetIndexContent(const std::string& index_content) { auto it = index_lines_lookup.find(index_line); if (it == index_lines_lookup.end()) - index_lines_lookup[index_line] = { i + 1 }; + index_lines_lookup[index_line] = {i + 1}; else it->second.push_back(i + 1); } @@ -68,7 +66,7 @@ void WorkingFile::OnBufferContentUpdated() { auto it = all_buffer_lines_lookup.find(buffer_line); if (it == all_buffer_lines_lookup.end()) - all_buffer_lines_lookup[buffer_line] = { i + 1 }; + all_buffer_lines_lookup[buffer_line] = {i + 1}; else it->second.push_back(i + 1); } @@ -86,14 +84,15 @@ optional WorkingFile::GetBufferLineFromIndexLine(int index_line) const { // Note: |index_line| and |buffer_line| are 1-based. // TODO: reenable this assert once we are using the real indexed file. - //assert(index_line >= 1 && index_line <= index_lines.size()); + // assert(index_line >= 1 && index_line <= index_lines.size()); if (index_line < 1 || index_line > index_lines.size()) { - std::cerr << "!! Bad index_line (got " << index_line << ", expected [1, " << index_lines.size() << "])" << std::endl; + std::cerr << "!! Bad index_line (got " << index_line << ", expected [1, " + << index_lines.size() << "])" << std::endl; return nullopt; } - // Find the line in the cached index file. We'll try to find the most similar line - // in the buffer and return the index for that. + // Find the line in the cached index file. We'll try to find the most similar + // line in the buffer and return the index for that. std::string index = index_lines[index_line - 1]; auto buffer_it = all_buffer_lines_lookup.find(index); if (buffer_it == all_buffer_lines_lookup.end()) { @@ -122,9 +121,10 @@ optional WorkingFile::GetIndexLineFromBufferLine(int buffer_line) const { // See GetBufferLineFromIndexLine for additional comments. // Note: |index_line| and |buffer_line| are 1-based. - //assert(buffer_line >= 1 && buffer_line < all_buffer_lines.size()); + // assert(buffer_line >= 1 && buffer_line < all_buffer_lines.size()); if (buffer_line < 1 || buffer_line > all_buffer_lines.size()) { - std::cerr << "!! Bad buffer_line (got " << buffer_line << ", expected [1, " << all_buffer_lines.size() << "])" << std::endl; + std::cerr << "!! Bad buffer_line (got " << buffer_line << ", expected [1, " + << all_buffer_lines.size() << "])" << std::endl; return nullopt; } @@ -154,7 +154,9 @@ optional WorkingFile::GetIndexLineFromBufferLine(int buffer_line) const { return closest_index_line; } -optional WorkingFile::GetBufferLineContentFromIndexLine(int indexed_line, optional* out_buffer_line) const { +optional WorkingFile::GetBufferLineContentFromIndexLine( + int indexed_line, + optional* out_buffer_line) const { optional buffer_line = GetBufferLineFromIndexLine(indexed_line); if (out_buffer_line) *out_buffer_line = buffer_line; @@ -163,14 +165,19 @@ optional WorkingFile::GetBufferLineContentFromIndexLine(int indexed return nullopt; if (*buffer_line < 1 || *buffer_line >= all_buffer_lines.size()) { - std::cerr << "GetBufferLineContentFromIndexLine buffer line lookup not in all_buffer_lines" << std::endl; + std::cerr << "GetBufferLineContentFromIndexLine buffer line lookup not in " + "all_buffer_lines" + << std::endl; return nullopt; } return all_buffer_lines[*buffer_line - 1]; } -std::string WorkingFile::FindClosestCallNameInBuffer(lsPosition position, int* active_parameter, lsPosition* completion_position) const { +std::string WorkingFile::FindClosestCallNameInBuffer( + lsPosition position, + int* active_parameter, + lsPosition* completion_position) const { *active_parameter = 0; int offset = GetOffsetForPosition(position, buffer_content); @@ -184,8 +191,10 @@ std::string WorkingFile::FindClosestCallNameInBuffer(lsPosition position, int* a int balance = 0; while (offset > 0) { char c = buffer_content[offset]; - if (c == ')') ++balance; - else if (c == '(') --balance; + if (c == ')') + ++balance; + else if (c == '(') + --balance; if (balance == 0 && c == ',') *active_parameter += 1; @@ -214,7 +223,10 @@ std::string WorkingFile::FindClosestCallNameInBuffer(lsPosition position, int* a return buffer_content.substr(offset, start_offset - offset + 1); } -lsPosition WorkingFile::FindStableCompletionSource(lsPosition position, bool* is_global_completion, std::string* existing_completion) const { +lsPosition WorkingFile::FindStableCompletionSource( + lsPosition position, + bool* is_global_completion, + std::string* existing_completion) const { *is_global_completion = true; int start_offset = GetOffsetForPosition(position, buffer_content); @@ -257,7 +269,8 @@ WorkingFile* WorkingFiles::GetFileByFilename(const std::string& filename) { return GetFileByFilenameNoLock(filename); } -WorkingFile* WorkingFiles::GetFileByFilenameNoLock(const std::string& filename) { +WorkingFile* WorkingFiles::GetFileByFilenameNoLock( + const std::string& filename) { for (auto& file : files) { if (file->filename == filename) return file.get(); @@ -273,7 +286,6 @@ void WorkingFiles::DoAction(const std::function& action) { void WorkingFiles::DoActionOnFile( const std::string& filename, const std::function& action) { - std::lock_guard lock(files_mutex); WorkingFile* file = GetFileByFilenameNoLock(filename); action(file); @@ -303,28 +315,33 @@ void WorkingFiles::OnChange(const Ipc_TextDocumentDidChange::Params& change) { std::string filename = change.textDocument.uri.GetPath(); WorkingFile* file = GetFileByFilenameNoLock(filename); if (!file) { - std::cerr << "Could not change " << filename << " because it was not open" << std::endl; + std::cerr << "Could not change " << filename << " because it was not open" + << std::endl; return; } file->version = change.textDocument.version; // std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - //std::cerr << "VERSION " << change.textDocument.version << std::endl; + // std::cerr << "VERSION " << change.textDocument.version << std::endl; - for (const Ipc_TextDocumentDidChange::lsTextDocumentContentChangeEvent& diff : change.contentChanges) { + for (const Ipc_TextDocumentDidChange::lsTextDocumentContentChangeEvent& diff : + change.contentChanges) { // std::cerr << "|" << file->buffer_content << "|" << std::endl; // If range or rangeLength are emitted we replace everything, per the spec. if (diff.rangeLength == -1) { file->buffer_content = diff.text; file->OnBufferContentUpdated(); // std::cerr << "-> Replacing entire content"; - } - else { - int start_offset = GetOffsetForPosition(diff.range.start, file->buffer_content); - // std::cerr << "-> Applying diff start=" << diff.range.start.ToString() << ", end=" << diff.range.end.ToString() << ", start_offset=" << start_offset << std::endl; - file->buffer_content.replace(file->buffer_content.begin() + start_offset, - file->buffer_content.begin() + start_offset + diff.rangeLength, - diff.text); + } else { + int start_offset = + GetOffsetForPosition(diff.range.start, file->buffer_content); + // std::cerr << "-> Applying diff start=" << diff.range.start.ToString() + // << ", end=" << diff.range.end.ToString() << ", start_offset=" << + // start_offset << std::endl; + file->buffer_content.replace( + file->buffer_content.begin() + start_offset, + file->buffer_content.begin() + start_offset + diff.rangeLength, + diff.text); file->OnBufferContentUpdated(); } @@ -332,7 +349,8 @@ void WorkingFiles::OnChange(const Ipc_TextDocumentDidChange::Params& change) { } // std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - //std::cerr << std::endl << std::endl << "--------" << file->content << "--------" << std::endl << std::endl; + // std::cerr << std::endl << std::endl << "--------" << file->content << + // "--------" << std::endl << std::endl; } void WorkingFiles::OnClose(const Ipc_TextDocumentDidClose::Params& close) { @@ -347,7 +365,8 @@ void WorkingFiles::OnClose(const Ipc_TextDocumentDidClose::Params& close) { } } - std::cerr << "Could not close " << filename << " because it was not open" << std::endl; + std::cerr << "Could not close " << filename << " because it was not open" + << std::endl; } std::vector WorkingFiles::AsUnsavedFiles() { @@ -362,82 +381,108 @@ std::vector WorkingFiles::AsUnsavedFiles() { TEST_SUITE("WorkingFile"); -lsPosition CharPos(const WorkingFile& file, char character, int character_offset = 0) { +lsPosition CharPos(const WorkingFile& file, + char character, + int character_offset = 0) { return CharPos(file.buffer_content, character, character_offset); } TEST_CASE("simple call") { WorkingFile f("foo.cc", "abcd(1, 2"); int active_param = 0; - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == + "abcd"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '1'), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '1'), &active_param) == + "abcd"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == + "abcd"); REQUIRE(active_param == 1); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == + "abcd"); REQUIRE(active_param == 1); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '2'), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '2'), &active_param) == + "abcd"); REQUIRE(active_param == 1); } TEST_CASE("nested call") { WorkingFile f("foo.cc", "abcd(efg(), 2"); int active_param = 0; - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == + "abcd"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'e'), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'e'), &active_param) == + "abcd"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'f'), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'f'), &active_param) == + "abcd"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g'), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g'), &active_param) == + "abcd"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 1), &active_param) == "efg"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 1), &active_param) == + "efg"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 2), &active_param) == "efg"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 2), &active_param) == + "efg"); REQUIRE(active_param == 0); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == + "abcd"); REQUIRE(active_param == 1); - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == "abcd"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == + "abcd"); REQUIRE(active_param == 1); } TEST_CASE("auto-insert )") { WorkingFile f("foo.cc", "abc()"); int active_param = 0; - REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ')'), &active_param) == "abc"); + REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ')'), &active_param) == + "abc"); REQUIRE(active_param == 0); } TEST_CASE("existing completion") { - // TODO: remove trailing space in zz.asdf. Lexing doesn't work correctly if done at the end of input. + // TODO: remove trailing space in zz.asdf. Lexing doesn't work correctly if + // done at the end of input. WorkingFile f("foo.cc", "zzz.asdf "); bool is_global_completion; std::string existing_completion; - f.FindStableCompletionSource(CharPos(f, '.'), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, '.'), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "zzz"); - f.FindStableCompletionSource(CharPos(f, 'a', 1), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, 'a', 1), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "a"); - f.FindStableCompletionSource(CharPos(f, 's', 1), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, 's', 1), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "as"); - f.FindStableCompletionSource(CharPos(f, 'd', 1), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, 'd', 1), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "asd"); - f.FindStableCompletionSource(CharPos(f, 'f', 1), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, 'f', 1), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "asdf"); } TEST_CASE("existing completion underscore") { - // TODO: remove trailing space in ABC_DEF. Lexing doesn't work correctly if done at the end of input. + // TODO: remove trailing space in ABC_DEF. Lexing doesn't work correctly if + // done at the end of input. WorkingFile f("foo.cc", "ABC_DEF "); bool is_global_completion; std::string existing_completion; - f.FindStableCompletionSource(CharPos(f, 'C'), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, 'C'), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "AB"); - f.FindStableCompletionSource(CharPos(f, '_'), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, '_'), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "ABC"); - f.FindStableCompletionSource(CharPos(f, 'D'), &is_global_completion, &existing_completion); + f.FindStableCompletionSource(CharPos(f, 'D'), &is_global_completion, + &existing_completion); REQUIRE(existing_completion == "ABC_"); } diff --git a/src/working_files.h b/src/working_files.h index ccf34000..7be4efe9 100644 --- a/src/working_files.h +++ b/src/working_files.h @@ -9,8 +9,8 @@ #include #include -using std::experimental::optional; using std::experimental::nullopt; +using std::experimental::optional; struct WorkingFile { int version = 0; @@ -28,7 +28,8 @@ struct WorkingFile { // Note: The items in the value entry are 1-based liness. std::unordered_map> all_buffer_lines_lookup; // A set of diagnostics that have been reported for this file. - // NOTE: _ is appended because it must be accessed under the WorkingFiles lock! + // NOTE: _ is appended because it must be accessed under the WorkingFiles + // lock! std::vector diagnostics_; WorkingFile(const std::string& filename, const std::string& buffer_content); @@ -45,16 +46,22 @@ struct WorkingFile { // accepts and returns 1-based lines. optional GetIndexLineFromBufferLine(int buffer_line) const; - optional GetBufferLineContentFromIndexLine(int indexed_line, optional* out_buffer_line) const; + optional GetBufferLineContentFromIndexLine( + int indexed_line, + optional* out_buffer_line) const; - // TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into lex_utils.h/cc + // TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into + // lex_utils.h/cc // Finds the closest 'callable' name prior to position. This is used for // signature help to filter code completion results. // // |completion_position| will be point to a good code completion location to // for fetching signatures. - std::string FindClosestCallNameInBuffer(lsPosition position, int* active_parameter, lsPosition* completion_position = nullptr) const; + std::string FindClosestCallNameInBuffer( + lsPosition position, + int* active_parameter, + lsPosition* completion_position = nullptr) const; // Returns a relatively stable completion position (it jumps back until there // is a non-alphanumeric character). @@ -63,7 +70,9 @@ struct WorkingFile { // global completion. // The out param |existing_completion| is set to any existing completion // content the user has entered. - lsPosition FindStableCompletionSource(lsPosition position, bool* is_global_completion, std::string* existing_completion) const; + lsPosition FindStableCompletionSource(lsPosition position, + bool* is_global_completion, + std::string* existing_completion) const; CXUnsavedFile AsUnsavedFile() const; }; @@ -79,8 +88,10 @@ struct WorkingFiles { // Run |action| under the lock. void DoAction(const std::function& action); - // Run |action| on the file identified by |filename|. This executes under the lock. - void DoActionOnFile(const std::string& filename, const std::function& action); + // Run |action| on the file identified by |filename|. This executes under the + // lock. + void DoActionOnFile(const std::string& filename, + const std::function& action); WorkingFile* OnOpen(const Ipc_TextDocumentDidOpen::Params& open); void OnChange(const Ipc_TextDocumentDidChange::Params& change); @@ -91,5 +102,5 @@ struct WorkingFiles { // Use unique_ptrs so we can handout WorkingFile ptrs and not have them // invalidated if we resize files. std::vector> files; - std::mutex files_mutex; // Protects |files|. + std::mutex files_mutex; // Protects |files|. }; \ No newline at end of file