diff --git a/src/iindexer.cc b/src/iindexer.cc index 9c700c03..3b838241 100644 --- a/src/iindexer.cc +++ b/src/iindexer.cc @@ -6,7 +6,7 @@ namespace { struct ClangIndexer : IIndexer { ~ClangIndexer() override = default; - std::vector> Index( + optional>> Index( Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, @@ -50,7 +50,7 @@ struct TestIndexer : IIndexer { ~TestIndexer() override = default; - std::vector> Index( + optional>> Index( Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, @@ -61,7 +61,7 @@ struct TestIndexer : IIndexer { if (it == indexes.end()) { // Don't return any indexes for unexpected data. assert(false && "no indexes"); - return {}; + return nullopt; } // FIXME: allow user to control how many times we return the index for a diff --git a/src/iindexer.h b/src/iindexer.h index 3604f47e..f8a45347 100644 --- a/src/iindexer.h +++ b/src/iindexer.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -32,7 +34,7 @@ struct IIndexer { std::initializer_list entries); virtual ~IIndexer() = default; - virtual std::vector> Index( + virtual optional>> Index( Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, diff --git a/src/import_pipeline.cc b/src/import_pipeline.cc index 1a6d8718..ab108947 100644 --- a/src/import_pipeline.cc +++ b/src/import_pipeline.cc @@ -321,9 +321,8 @@ void ParseFile(Config* config, ImportManager* import_manager, ICacheManager* cache_manager, IIndexer* indexer, - bool is_interactive, - const Project::Entry& entry, - const std::string& entry_contents) { + const Index_Request& request, + const Project::Entry& entry) { // If the file is inferred, we may not actually be able to parse that file // directly (ie, a header file, which are not listed in the project). If this // file is inferred, then try to use the file which originally imported it. @@ -337,33 +336,46 @@ void ParseFile(Config* config, // Try to load the file from cache. if (TryLoadFromCache(file_consumer_shared, timestamp_manager, modification_timestamp_fetcher, import_manager, - cache_manager, is_interactive, entry, + cache_manager, request.is_interactive, entry, path_to_index) == CacheLoadResult::DoNotParse) { return; } LOG_S(INFO) << "Parsing " << path_to_index; - std::vector file_contents = - PreloadFileContents(cache_manager, entry, entry_contents, path_to_index); + std::vector file_contents = PreloadFileContents( + cache_manager, entry, request.contents, path_to_index); std::vector result; PerformanceImportFile perf; - std::vector> indexes = - indexer->Index(config, file_consumer_shared, path_to_index, entry.args, - file_contents, &perf); - for (std::unique_ptr& new_index : indexes) { + auto indexes = indexer->Index(config, file_consumer_shared, path_to_index, + entry.args, file_contents, &perf); + + if (!indexes) { + if (config->enableIndexing && + std::holds_alternative(request.id)) { + Out_Error out; + out.id = request.id; + out.error.code = lsErrorCodes::InternalError; + out.error.message = "Failed to index " + path_to_index; + QueueManager::WriteStdout(IpcId::Unknown, out); + } + return; + } + + for (std::unique_ptr& new_index : *indexes) { Timer time; // Only emit diagnostics for non-interactive sessions, which makes it easier // to identify indexing problems. For interactive sessions, diagnostics are // handled by code completion. - if (!is_interactive) + if (!request.is_interactive) EmitDiagnostics(working_files, new_index->path, new_index->diagnostics_); // When main thread does IdMap request it will request the previous index if // needed. LOG_S(INFO) << "Emitting index result for " << new_index->path; - result.push_back(Index_DoIdMap(std::move(new_index), perf, is_interactive, + result.push_back(Index_DoIdMap(std::move(new_index), perf, + request.is_interactive, true /*write_to_disk*/)); } @@ -389,7 +401,7 @@ bool IndexMain_DoParse( entry.args = request->args; ParseFile(config, working_files, file_consumer_shared, timestamp_manager, modification_timestamp_fetcher, import_manager, cache_manager, - indexer, request->is_interactive, entry, request->contents); + indexer, request.value(), entry); return true; } @@ -518,11 +530,13 @@ void IndexWithTuFromCodeCompletion( PerformanceImportFile perf; ClangIndex index; - std::vector> indexes = ParseWithTu( + auto indexes = ParseWithTu( file_consumer_shared, &perf, tu, &index, path, args, file_contents); + if (!indexes) + return; std::vector result; - for (std::unique_ptr& new_index : indexes) { + for (std::unique_ptr& new_index : *indexes) { Timer time; // When main thread does IdMap request it will request the previous index if diff --git a/src/indexer.cc b/src/indexer.cc index 04256fb1..4088c41c 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1894,7 +1894,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) { } } -std::vector> Parse( +optional>> Parse( Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, @@ -1924,7 +1924,7 @@ std::vector> Parse( CXTranslationUnit_KeepGoing | CXTranslationUnit_DetailedPreprocessingRecord); if (!tu) - return {}; + return nullopt; perf->index_parse = timer.ElapsedMicrosecondsAndReset(); @@ -1935,7 +1935,7 @@ std::vector> Parse( unsaved_files); } -std::vector> ParseWithTu( +optional>> ParseWithTu( FileConsumerSharedState* file_consumer_shared, PerformanceImportFile* perf, ClangTranslationUnit* tu, @@ -1982,8 +1982,9 @@ std::vector> ParseWithTu( CXIndexOpt_IndexImplicitTemplateInstantiations, tu->cx_tu); if (index_result != CXError_Success) { - LOG_S(WARNING) << "Indexing " << file - << " failed with errno=" << index_result; + LOG_S(ERROR) << "Indexing " << file + << " failed with errno=" << index_result; + return nullopt; } clang_IndexAction_dispose(index_action); diff --git a/src/indexer.h b/src/indexer.h index 1ecbe796..93f4e5ec 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -539,7 +539,7 @@ struct NamespaceHelper { // |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. -std::vector> Parse( +optional>> Parse( Config* config, FileConsumerSharedState* file_consumer_shared, std::string file, @@ -548,7 +548,7 @@ std::vector> Parse( PerformanceImportFile* perf, ClangIndex* index, bool dump_ast = false); -std::vector> ParseWithTu( +optional>> ParseWithTu( FileConsumerSharedState* file_consumer_shared, PerformanceImportFile* perf, ClangTranslationUnit* tu, diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 075eb3df..d4904fd6 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -221,8 +221,9 @@ struct InitializeHandler : BaseMessageHandler { } bool is_interactive = working_files->GetFileByFilename(entry.filename) != nullptr; - queue->index_request.Enqueue(Index_Request( - entry.filename, entry.args, is_interactive, *content)); + queue->index_request.Enqueue( + Index_Request(entry.filename, entry.args, is_interactive, + *content, request->id)); }); // We need to support multiple concurrent index processes. diff --git a/src/queue_manager.cc b/src/queue_manager.cc index 3132d729..8f52b41b 100644 --- a/src/queue_manager.cc +++ b/src/queue_manager.cc @@ -8,11 +8,13 @@ Index_Request::Index_Request(const std::string& path, const std::vector& args, bool is_interactive, - const std::string& contents) + const std::string& contents, + lsRequestId id) : path(path), args(args), is_interactive(is_interactive), - contents(contents) {} + contents(contents), + id(id) {} Index_DoIdMap::Index_DoIdMap(std::unique_ptr current, PerformanceImportFile perf, diff --git a/src/queue_manager.h b/src/queue_manager.h index f652aa57..a387ed94 100644 --- a/src/queue_manager.h +++ b/src/queue_manager.h @@ -20,11 +20,13 @@ struct Index_Request { std::vector args; bool is_interactive; std::string contents; // Preloaded contents. Useful for tests. + lsRequestId id; Index_Request(const std::string& path, const std::vector& args, bool is_interactive, - const std::string& contents); + const std::string& contents, + lsRequestId id={}); }; struct Index_DoIdMap { diff --git a/src/test.cc b/src/test.cc index 7592d701..e83004f7 100644 --- a/src/test.cc +++ b/src/test.cc @@ -170,9 +170,9 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) { Config config; FileConsumerSharedState file_consumer_shared; PerformanceImportFile perf; - std::vector> dbs = - Parse(&config, &file_consumer_shared, path, flags, {}, &perf, &index, - false /*dump_ast*/); + auto dbs = Parse(&config, &file_consumer_shared, path, flags, {}, &perf, + &index, false /*dump_ast*/); + assert(dbs); for (const auto& entry : all_expected_output) { const std::string& expected_path = entry.first; @@ -203,7 +203,7 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) { }; // Get output from index operation. - IndexFile* db = FindDbForPathEnding(expected_path, dbs); + IndexFile* db = FindDbForPathEnding(expected_path, *dbs); assert(db); if (!db->diagnostics_.empty()) { std::cout << "For " << path << std::endl;