diff --git a/src/command_line.cc b/src/command_line.cc index 072cfada..25f2e7c7 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -776,12 +776,17 @@ struct Index_DoIndex { Freshen, }; - Index_DoIndex(Type type, const Project::Entry& entry, optional content) - : type(type), entry(entry), content(content) {} + Index_DoIndex(Type type, const Project::Entry& entry, optional content, bool show_diagnostics) + : type(type), entry(entry), content(content), show_diagnostics(show_diagnostics) {} + // Type of index operation. Type type; + // Project entry for file path and file arguments. Project::Entry entry; + // File contents that should be indexed. optional content; + // If diagnostics should be reported. + bool show_diagnostics = false; }; struct Index_DoIdMap { @@ -1020,10 +1025,12 @@ bool ImportCachedIndex(IndexerConfig* config, } void ParseFile(IndexerConfig* config, + WorkingFiles* working_files, FileConsumer::SharedState* file_consumer_shared, Index_DoIdMapQueue* queue_do_id_map, const Project::Entry& entry, - const optional& indexed_content) { + const optional& indexed_content, + bool report_diagnostics) { std::unique_ptr cache_for_args = LoadCachedIndex(config, entry.filename); @@ -1053,12 +1060,19 @@ void ParseFile(IndexerConfig* config, // Note: we are reusing the parent perf. perf.index_load_cached = time.ElapsedMicrosecondsAndReset(); - // Publish diagnostics. - if (!new_index->diagnostics.empty() || (cached_index && !cached_index->diagnostics.empty())) { - Out_TextDocumentPublishDiagnostics diag; - diag.params.uri = lsDocumentUri::FromPath(new_index->path); - diag.params.diagnostics = new_index->diagnostics; - IpcManager::instance()->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diag); + // Publish diagnostics. We guard behind a |report_diagnostics| flag to + // avoid heavy lock contention in working_files->GetFileByFilename(). + if (report_diagnostics) { + WorkingFile* file = working_files->GetFileByFilename(new_index->path); + if ((file && file->has_diagnostics) || !new_index->diagnostics.empty()) { + if (file) + file->has_diagnostics = !new_index->diagnostics.empty(); + + Out_TextDocumentPublishDiagnostics diag; + diag.params.uri = lsDocumentUri::FromPath(new_index->path); + diag.params.diagnostics = new_index->diagnostics; + IpcManager::instance()->SendOutMessageToClient(IpcId::TextDocumentPublishDiagnostics, diag); + } } @@ -1125,6 +1139,7 @@ bool ResetStaleFiles(IndexerConfig* config, bool IndexMain_DoIndex(IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, Project* project, + WorkingFiles* working_files, Index_DoIndexQueue* queue_do_index, Index_DoIdMapQueue* queue_do_id_map) { optional index_request = queue_do_index->TryDequeue(); @@ -1155,7 +1170,7 @@ bool IndexMain_DoIndex(IndexerConfig* config, case Index_DoIndex::Type::Parse: { // index_request->path can be a cc/tu or a dependency path. file_consumer_shared->Reset(index_request->entry.filename); - ParseFile(config, file_consumer_shared, queue_do_id_map, index_request->entry, index_request->content); + ParseFile(config, working_files, file_consumer_shared, queue_do_id_map, index_request->entry, index_request->content, index_request->show_diagnostics); break; } @@ -1165,7 +1180,7 @@ bool IndexMain_DoIndex(IndexerConfig* config, bool needs_reparse = ResetStaleFiles(config, file_consumer_shared, index_request->entry.filename); if (needs_reparse) - ParseFile(config, file_consumer_shared, queue_do_id_map, index_request->entry, index_request->content); + ParseFile(config, working_files, file_consumer_shared, queue_do_id_map, index_request->entry, index_request->content, index_request->show_diagnostics); break; } } @@ -1239,6 +1254,7 @@ void IndexMain( IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, Project* project, + WorkingFiles* working_files, MultiQueueWaiter* waiter, Index_DoIndexQueue* queue_do_index, Index_DoIdMapQueue* queue_do_id_map, @@ -1255,7 +1271,7 @@ void 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_index = IndexMain_DoIndex(config, file_consumer_shared, project, queue_do_index, queue_do_id_map); + bool did_index = IndexMain_DoIndex(config, file_consumer_shared, project, working_files, queue_do_index, queue_do_id_map); bool did_create_update = IndexMain_DoCreateIndexUpdate(queue_on_id_mapped, queue_on_indexed); bool did_merge = false; @@ -1342,7 +1358,7 @@ bool QueryDbMainLoop( 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; + //std::cerr << "[querydb] Processing message " << IpcIdToString(message->method_id) << std::endl; switch (message->method_id) { case IpcId::Initialize: { @@ -1384,7 +1400,7 @@ bool QueryDbMainLoop( std::cerr << "[querydb] Starting " << indexer_count << " indexers" << std::endl; for (int i = 0; i < indexer_count; ++i) { new std::thread([&]() { - IndexMain(config, file_consumer_shared, project, waiter, queue_do_index, queue_do_id_map, queue_on_id_mapped, queue_on_indexed); + IndexMain(config, file_consumer_shared, project, working_files, waiter, queue_do_index, queue_do_id_map, queue_on_id_mapped, queue_on_indexed); }); } @@ -1397,7 +1413,7 @@ bool QueryDbMainLoop( << "] Dispatching index request for file " << entry.filename << std::endl; - queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::ImportThenParse, entry, nullopt)); + queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::ImportThenParse, entry, nullopt, false /*show_diagnostics*/)); }); } @@ -1453,7 +1469,7 @@ bool QueryDbMainLoop( std::cerr << "[" << i << "/" << (project->entries.size() - 1) << "] Dispatching index request for file " << entry.filename << std::endl; - queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::Freshen, entry, nullopt)); + queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::Freshen, entry, nullopt, false /*show_diagnostics*/)); }); break; } @@ -1625,7 +1641,7 @@ bool QueryDbMainLoop( // if so, ignore that index response. WorkingFile* working_file = working_files->GetFileByFilename(path); if (working_file) - queue_do_index->PriorityEnqueue(Index_DoIndex(Index_DoIndex::Type::Parse, project->FindCompilationEntryForFile(path), working_file->buffer_content)); + queue_do_index->PriorityEnqueue(Index_DoIndex(Index_DoIndex::Type::Parse, project->FindCompilationEntryForFile(path), working_file->buffer_content, true /*show_diagnostics*/)); completion_manager->UpdateActiveSession(path); break; diff --git a/src/indexer.h b/src/indexer.h index 6c06a5de..07fee29b 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -474,9 +474,6 @@ struct IndexFile { // header we need to lookup the original translation unit and reindex that. std::string import_file; - // The content of |path| when it was indexed. - //std::string content; - // Diagnostics found when indexing the file. This is not saved. NonElidedVector diagnostics; diff --git a/src/serializer.cc b/src/serializer.cc index cd374c35..43c4a23b 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -231,7 +231,6 @@ void Reflect(TVisitor& visitor, IndexFile& value) { REFLECT_MEMBER(last_modification_time); REFLECT_MEMBER(import_file); REFLECT_MEMBER(args); - REFLECT_MEMBER(diagnostics); } REFLECT_MEMBER(dependencies); REFLECT_MEMBER(types); diff --git a/src/test.cc b/src/test.cc index 12dd7da6..345e6af3 100644 --- a/src/test.cc +++ b/src/test.cc @@ -119,6 +119,7 @@ void RunTests() { // Run test. std::cout << "[START] " << path << std::endl; + PerformanceImportFile perf; std::vector> dbs = Parse( &config, &file_consumer_shared, path, @@ -131,7 +132,7 @@ void RunTests() { "-IC:/Users/jacob/Desktop/superindex/indexer/src" }, "", nullopt, - nullptr, + &perf, false /*dump_ast*/); #if false diff --git a/src/working_files.h b/src/working_files.h index 9c59b9af..0b498ba7 100644 --- a/src/working_files.h +++ b/src/working_files.h @@ -27,6 +27,8 @@ struct WorkingFile { // This map goes from buffer-line -> indices+1 in all_buffer_lines. // Note: The items in the value entry are 1-based liness. std::unordered_map> all_buffer_lines_lookup; + // True iff this file currently has reported diagnostics. + bool has_diagnostics = false; WorkingFile(const std::string& filename, const std::string& buffer_content);