From 278eb0cd77db98404b3a4cace28753970c42a4b0 Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Sat, 22 Apr 2017 00:32:29 -0700 Subject: [PATCH] Better support for removing data from querydb --- src/command_line.cc | 370 +++++++++++++++++++++++++++++--------------- src/query.cc | 142 ++++++++--------- src/query.h | 25 +-- 3 files changed, 307 insertions(+), 230 deletions(-) diff --git a/src/command_line.cc b/src/command_line.cc index feca14fd..b39b0f8c 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -293,8 +293,11 @@ void PushBack(NonElidedVector* result, optional location QueryFile* FindFile(QueryDatabase* db, const std::string& filename, QueryFileId* file_id) { auto it = db->usr_to_symbol.find(filename); if (it != db->usr_to_symbol.end()) { - *file_id = QueryFileId(it->second.idx); - return &db->files[it->second.idx]; + optional& file = db->files[it->second.idx]; + if (file) { + *file_id = QueryFileId(it->second.idx); + return &file.value(); + } } std::cerr << "Unable to find file " << filename << std::endl; @@ -305,69 +308,137 @@ QueryFile* FindFile(QueryDatabase* db, const std::string& filename, QueryFileId* QueryFile* FindFile(QueryDatabase* db, const std::string& filename) { // TODO: consider calling NormalizePath here. It might add too much latency though. auto it = db->usr_to_symbol.find(filename); - if (it != db->usr_to_symbol.end()) - return &db->files[it->second.idx]; + if (it != db->usr_to_symbol.end()) { + optional& file = db->files[it->second.idx]; + if (file) + return &file.value(); + } std::cerr << "Unable to find file " << filename << std::endl; return nullptr; } -QueryFile* GetQuery(QueryDatabase* db, const QueryFileId& id) { +optional* GetQuery(QueryDatabase* db, const QueryFileId& id) { return &db->files[id.id]; } -QueryType* GetQuery(QueryDatabase* db, const QueryTypeId& id) { +optional* GetQuery(QueryDatabase* db, const QueryTypeId& id) { return &db->types[id.id]; } -QueryFunc* GetQuery(QueryDatabase* db, const QueryFuncId& id) { +optional* GetQuery(QueryDatabase* db, const QueryFuncId& id) { return &db->funcs[id.id]; } -QueryVar* GetQuery(QueryDatabase* db, const QueryVarId& id) { +optional* GetQuery(QueryDatabase* db, const QueryVarId& id) { return &db->vars[id.id]; } - optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryTypeId& id) { - return GetQuery(db, id)->def.definition_spelling; + optional& type = db->types[id.id]; + if (type) + return type->def.definition_spelling; + return nullopt; } + optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryFuncId& id) { - return GetQuery(db, id)->def.definition_spelling; + optional& func = db->funcs[id.id]; + if (func) + return func->def.definition_spelling; + return nullopt; } + optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryVarId& id) { - return GetQuery(db, id)->def.definition_spelling; + optional& var = db->vars[id.id]; + if (var) + return var->def.definition_spelling; + return nullopt; } + optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: - return db->types[symbol.idx].def.definition_spelling; - case SymbolKind::Func: - return db->funcs[symbol.idx].def.definition_spelling; - case SymbolKind::Var: - return db->vars[symbol.idx].def.definition_spelling; - 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) { + 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; + } + } + return nullopt; +} std::string GetHoverForSymbol(QueryDatabase* db, const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: - return db->types[symbol.idx].def.detailed_name; - case SymbolKind::Func: - return db->funcs[symbol.idx].def.detailed_name; - case SymbolKind::Var: - return db->vars[symbol.idx].def.detailed_name; - 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 ""; } @@ -414,19 +485,30 @@ std::vector ToQueryLocation(QueryDatabase* db, const std::vector< std::vector GetUsesOfSymbol(QueryDatabase* db, const SymbolIdx& symbol) { switch (symbol.kind) { - case SymbolKind::Type: - return db->types[symbol.idx].uses; + 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. - const QueryFunc& func = db->funcs[symbol.idx]; - 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; + 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::Var: - return db->vars[symbol.idx].uses; case SymbolKind::File: case SymbolKind::Invalid: { assert(false && "unexpected"); @@ -436,34 +518,6 @@ std::vector GetUsesOfSymbol(QueryDatabase* db, const SymbolIdx& s return {}; } -optional GetDefinitionExtentOfSymbol(QueryDatabase* db, const QueryTypeId& id) { - return GetQuery(db, id)->def.definition_extent; -} -optional GetDefinitionExtentOfSymbol(QueryDatabase* db, const QueryFuncId& id) { - return GetQuery(db, id)->def.definition_extent; -} -optional GetDefinitionExtentOfSymbol(QueryDatabase* db, const QueryVarId& id) { - return GetQuery(db, id)->def.definition_extent; -} -optional GetDefinitionExtentOfSymbol(QueryDatabase* db, const SymbolIdx& symbol) { - switch (symbol.kind) { - case SymbolKind::File: - // TODO: If line 1 is deleted the file won't show up in, ie, workspace symbol search results. - return QueryLocation(QueryFileId(symbol.idx), Range(Position(1, 1), Position(1, 1))); - case SymbolKind::Type: - return db->types[symbol.idx].def.definition_extent; - case SymbolKind::Func: - return db->funcs[symbol.idx].def.definition_extent; - case SymbolKind::Var: - return db->vars[symbol.idx].def.definition_extent; - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } - } - return nullopt; -} - std::vector GetDeclarationsOfSymbolForGotoDefinition(QueryDatabase* db, const SymbolIdx& symbol) { switch (symbol.kind) { case SymbolKind::Type: { @@ -471,17 +525,27 @@ std::vector GetDeclarationsOfSymbolForGotoDefinition(QueryDatabas // 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 declaration = db->types[symbol.idx].def.definition_spelling; - if (declaration) - return { *declaration }; + optional& type = db->types[symbol.idx]; + if (type) { + optional declaration = type->def.definition_spelling; + if (declaration) + return { *declaration }; + } + break; + } + case SymbolKind::Func: { + optional& func = db->funcs[symbol.idx]; + if (func) + return func->declarations; break; } - case SymbolKind::Func: - return db->funcs[symbol.idx].declarations; case SymbolKind::Var: { - optional declaration = db->vars[symbol.idx].def.declaration; - if (declaration) - return { *declaration }; + optional& var = db->vars[symbol.idx]; + if (var) { + optional declaration = var->def.declaration; + if (declaration) + return { *declaration }; + } break; } } @@ -492,10 +556,13 @@ std::vector GetDeclarationsOfSymbolForGotoDefinition(QueryDatabas optional GetBaseDefinitionOrDeclarationSpelling(QueryDatabase* db, QueryFunc& func) { if (!func.def.base) return nullopt; - QueryFunc& base = db->funcs[func.def.base->id]; - auto def = base.def.definition_spelling; - if (!def && !base.declarations.empty()) - def = base.declarations[0]; + optional& base = db->funcs[func.def.base->id]; + if (!base) + return nullopt; + + auto def = base->def.definition_spelling; + if (!def && !base->declarations.empty()) + def = base->declarations[0]; return def; } @@ -504,9 +571,12 @@ std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, Query optional func_id = root.def.base; while (func_id) { - QueryFunc& func = db->funcs[func_id->id]; - AddRange(&callers, func.callers); - func_id = func.def.base; + optional& func = db->funcs[func_id->id]; + if (!func) + break; + + AddRange(&callers, func->callers); + func_id = func->def.base; } return callers; @@ -519,11 +589,13 @@ std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, Qu PushRange(&queue, root.derived); while (!queue.empty()) { - QueryFunc& func = db->funcs[queue.front().id]; + optional& func = db->funcs[queue.front().id]; queue.pop(); - PushRange(&queue, func.derived); + if (!func) + continue; - AddRange(&callers, func.callers); + PushRange(&queue, func->derived); + AddRange(&callers, func->callers); } return callers; @@ -547,13 +619,25 @@ optional GetLsRange(WorkingFile* working_file, const Range& location) { } lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id, std::string* path) { - *path = db->files[file_id.id].def.path; - return lsDocumentUri::FromPath(*path); + optional& file = db->files[file_id.id]; + if (file) { + *path = file->def.path; + return lsDocumentUri::FromPath(*path); + } + else { + *path = ""; + return lsDocumentUri::FromPath(""); + } } lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id) { - std::string path = db->files[file_id.id].def.path; - return lsDocumentUri::FromPath(path); + optional& file = db->files[file_id.id]; + if (file) { + return lsDocumentUri::FromPath(file->def.path); + } + else { + return lsDocumentUri::FromPath(""); + } } optional GetLsLocation(QueryDatabase* db, WorkingFiles* working_files, const QueryLocation& location) { @@ -567,46 +651,62 @@ optional GetLsLocation(QueryDatabase* db, WorkingFiles* working_file // Returns a symbol. The symbol will have *NOT* have a location assigned. optional GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, SymbolIdx symbol) { - lsSymbolInformation info; - - switch (symbol.kind) { + switch (symbol.kind) { case SymbolKind::File: { - QueryFile* file = symbol.ResolveFile(db); + optional& file = db->files[symbol.idx]; + if (!file) + return nullopt; + + lsSymbolInformation info; info.name = file->def.path; info.kind = lsSymbolKind::File; - break; + return info; } case SymbolKind::Type: { - QueryType* type = symbol.ResolveType(db); + optional& type = db->types[symbol.idx]; + if (!type) + return nullopt; + + lsSymbolInformation info; info.name = type->def.detailed_name; info.kind = lsSymbolKind::Class; - break; + return info; } case SymbolKind::Func: { - QueryFunc* func = symbol.ResolveFunc(db); + optional& func = db->funcs[symbol.idx]; + if (!func) + return nullopt; + lsSymbolInformation info; info.name = func->def.detailed_name; + info.kind = lsSymbolKind::Function; + if (func->def.declaring_type.has_value()) { - info.kind = lsSymbolKind::Method; - info.containerName = db->types[func->def.declaring_type->id].def.detailed_name; + optional& container = db->types[func->def.declaring_type->id]; + if (container) { + info.kind = lsSymbolKind::Method; + info.containerName = container->def.detailed_name; + } } - else { - info.kind = lsSymbolKind::Function; - } - break; + + return info; } case SymbolKind::Var: { - QueryVar* var = symbol.ResolveVar(db); + optional& var = db->vars[symbol.idx]; + if (!var) + return nullopt; + + lsSymbolInformation info; info.name += var->def.detailed_name; info.kind = lsSymbolKind::Variable; - break; + return info; } case SymbolKind::Invalid: { return nullopt; } }; - return info; + return nullopt; } struct CommonCodeLensParams { @@ -669,7 +769,11 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, WorkingFiles* working_file if (path_to_edit.find(location.path) == path_to_edit.end()) { path_to_edit[location.path] = lsTextDocumentEdit(); - const std::string& path = db->files[location.path.id].def.path; + optional& file = db->files[location.path.id]; + if (!file) + continue; + + const std::string& path = file->def.path; path_to_edit[location.path].textDocument.uri = lsDocumentUri::FromPath(path); WorkingFile* working_file = working_files->GetFileByFilename(path); @@ -1203,26 +1307,28 @@ void QueryDbMainLoop( } 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. + + Timer time; auto msg = static_cast(message.get()); - //std::cerr << "Opening " << msg->params.textDocument.uri.GetPath() << std::endl; WorkingFile* working_file = working_files->OnOpen(msg->params); optional cached_file_contents = LoadCachedFileContents(config, msg->params.textDocument.uri.GetPath()); if (cached_file_contents) working_file->SetIndexContent(*cached_file_contents); else working_file->SetIndexContent(working_file->buffer_content); + time.ResetAndPrint("[querydb] Loading cached index file for DidOpen"); break; } case IpcId::TextDocumentDidChange: { auto msg = static_cast(message.get()); working_files->OnChange(msg->params); - //std::cerr << "Changing " << msg->params.textDocument.uri.GetPath() << std::endl; break; } case IpcId::TextDocumentDidClose: { auto msg = static_cast(message.get()); - //std::cerr << "Closing " << msg->params.textDocument.uri.GetPath() << std::endl; working_files->OnClose(msg->params); break; } @@ -1518,36 +1624,39 @@ void QueryDbMainLoop( SymbolIdx symbol = ref.idx; switch (symbol.kind) { case SymbolKind::Type: { - QueryType& type = db->types[symbol.idx]; - AddCodeLens(&common, ref.loc.OffsetStartColumn(0), type.uses, "ref", "refs"); - AddCodeLens(&common, ref.loc.OffsetStartColumn(1), ToQueryLocation(db, type.derived), "derived", "derived"); - AddCodeLens(&common, ref.loc.OffsetStartColumn(2), ToQueryLocation(db, type.instances), "var", "vars"); + optional& type = db->types[symbol.idx]; + if (!type) + continue; + AddCodeLens(&common, ref.loc.OffsetStartColumn(0), type->uses, "ref", "refs"); + AddCodeLens(&common, ref.loc.OffsetStartColumn(1), ToQueryLocation(db, type->derived), "derived", "derived"); + AddCodeLens(&common, ref.loc.OffsetStartColumn(2), ToQueryLocation(db, type->instances), "var", "vars"); break; } case SymbolKind::Func: { - QueryFunc& func = db->funcs[symbol.idx]; - + optional& func = db->funcs[symbol.idx]; + if (!func) + continue; int offset = 0; - std::vector base_callers = GetCallersForAllBaseFunctions(db, func); - std::vector derived_callers = GetCallersForAllDerivedFunctions(db, func); + std::vector base_callers = GetCallersForAllBaseFunctions(db, *func); + std::vector derived_callers = GetCallersForAllDerivedFunctions(db, *func); if (base_callers.empty() && derived_callers.empty()) { // set exclude_loc to true to force the code lens to show up - AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func.callers), "call", "calls", true /*exclude_loc*/); + AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func->callers), "call", "calls", true /*exclude_loc*/); } else { - AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func.callers), "direct call", "direct calls"); + AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func->callers), "direct call", "direct calls"); if (!base_callers.empty()) AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, base_callers), "base call", "base calls"); if (!derived_callers.empty()) AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, derived_callers), "derived call", "derived calls"); } - AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func.derived), "derived", "derived"); + AddCodeLens(&common, ref.loc.OffsetStartColumn(offset++), ToQueryLocation(db, func->derived), "derived", "derived"); // "Base" - optional base_loc = GetBaseDefinitionOrDeclarationSpelling(db, func); + optional base_loc = GetBaseDefinitionOrDeclarationSpelling(db, *func); if (base_loc) { optional ls_base = GetLsLocation(db, working_files, *base_loc); if (ls_base) { @@ -1569,8 +1678,11 @@ void QueryDbMainLoop( break; } case SymbolKind::Var: { - QueryVar& var = db->vars[symbol.idx]; - AddCodeLens(&common, ref.loc.OffsetStartColumn(0), var.uses, "ref", "refs", true /*exclude_loc*/); + optional& var = db->vars[symbol.idx]; + if (!var) + continue; + + AddCodeLens(&common, ref.loc.OffsetStartColumn(0), var->uses, "ref", "refs", true /*exclude_loc*/); break; } case SymbolKind::File: diff --git a/src/query.cc b/src/query.cc index c534e4d9..71259e96 100644 --- a/src/query.cc +++ b/src/query.cc @@ -69,8 +69,6 @@ void AddMergeableRange( // time at the cost of some additional memory. // Build lookup table. - //google::dense_hash_map> id_to_index; - //id_to_index.set_empty_key(TId(-1)); spp::sparse_hash_map id_to_index; id_to_index.resize(dest->size()); for (size_t i = 0; i < dest->size(); ++i) @@ -232,49 +230,6 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexedFile& indexed) { - - - - - - - -QueryFile* SymbolIdx::ResolveFile(QueryDatabase* db) const { - assert(kind == SymbolKind::File); - return &db->files[idx]; -} -QueryType* SymbolIdx::ResolveType(QueryDatabase* db) const { - assert(kind == SymbolKind::Type); - return &db->types[idx]; -} -QueryFunc* SymbolIdx::ResolveFunc(QueryDatabase* db) const { - assert(kind == SymbolKind::Func); - return &db->funcs[idx]; -} -QueryVar* SymbolIdx::ResolveVar(QueryDatabase* db) const { - assert(kind == SymbolKind::Var); - return &db->vars[idx]; -} - - - - - - - - - - - - - - - - - - - - @@ -349,17 +304,14 @@ IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids) : local_ids(local_ids) { primary_file = GetQueryFileIdFromPath(query_db, local_ids.primary_file); - //cached_type_ids_.set_empty_key(IndexTypeId(-1)); 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_func_ids_.set_empty_key(IndexFuncId(-1)); 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_var_ids_.set_empty_key(IndexVarId(-1)); cached_var_ids_.resize(local_ids.var_id_to_usr.size()); for (const auto& entry : local_ids.var_id_to_usr) cached_var_ids_[entry.first] = GetQueryVarIdFromUsr(query_db, entry.second); @@ -646,24 +598,51 @@ void IndexUpdate::Merge(const IndexUpdate& update) { void QueryDatabase::RemoveUsrs(const std::vector& to_remove) { // This function runs on the querydb thread. - // Actually removing data is extremely slow because every offset/index would - // have to be updated. Instead, we just accept the memory overhead and mark - // the symbol as invalid. + // When we remove an element, we just erase the state from the storage. We do + // not update array indices because that would take a huge amount of time for + // a very large index. // - // If the user wants to reduce memory usage, they will have to restart the - // indexer and load it from cache. Luckily, this doesn't take too long even - // on large projects (1-2 minutes). + // There means that there is some memory growth that will never be reclaimed, + // but it should be pretty minimal and is solved by simply restarting the + // indexer and loading from cache, which is a fast operation. + // + // TODO: Add "cquery: Reload Index" command which unloads all querydb state + // and fully reloads from cache. This will address the memory leak above. - for (Usr usr : to_remove) - usr_to_symbol[usr].kind = SymbolKind::Invalid; + for (Usr usr : to_remove) { + SymbolIdx& symbol = usr_to_symbol[usr]; + switch (symbol.kind) { + case SymbolKind::File: + files[symbol.idx] = nullopt; + break; + case SymbolKind::Type: + types[symbol.idx] = nullopt; + break; + case SymbolKind::Func: + funcs[symbol.idx] = nullopt; + break; + case SymbolKind::Var: + vars[symbol.idx] = nullopt; + break; + } + + symbol.kind = SymbolKind::Invalid; + } } void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) { // 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]; \ + 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); \ } @@ -697,9 +676,12 @@ void QueryDatabase::ImportOrUpdate(const std::vector& upda auto it = usr_to_symbol.find(def.path); assert(it != usr_to_symbol.end()); - QueryFile& existing = files[it->second.idx]; - existing.def = def; - UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::File, it->second.idx, def.path); + optional& existing = files[it->second.idx]; + if (!existing) + existing = QueryFile(def.path); + + existing->def = def; + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::File, it->second.idx, def.path); } } @@ -712,14 +694,16 @@ void QueryDatabase::ImportOrUpdate(const std::vector& upda auto it = usr_to_symbol.find(def.usr); assert(it != usr_to_symbol.end()); - QueryType& existing = types[it->second.idx]; + optional& existing = types[it->second.idx]; + if (!existing) + existing = QueryType(def.usr); // Keep the existing definition if it is higher quality. - if (existing.def.definition_spelling && !def.definition_spelling) + if (existing->def.definition_spelling && !def.definition_spelling) continue; - existing.def = def; - UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::Type, it->second.idx, def.detailed_name); + existing->def = def; + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Type, it->second.idx, def.detailed_name); } } @@ -732,14 +716,16 @@ void QueryDatabase::ImportOrUpdate(const std::vector& upda auto it = usr_to_symbol.find(def.usr); assert(it != usr_to_symbol.end()); - QueryFunc& existing = funcs[it->second.idx]; + optional& existing = funcs[it->second.idx]; + if (!existing) + existing = QueryFunc(def.usr); // Keep the existing definition if it is higher quality. - if (existing.def.definition_spelling && !def.definition_spelling) + if (existing->def.definition_spelling && !def.definition_spelling) continue; - existing.def = def; - UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::Func, it->second.idx, def.detailed_name); + existing->def = def; + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Func, it->second.idx, def.detailed_name); } } @@ -752,15 +738,17 @@ void QueryDatabase::ImportOrUpdate(const std::vector& updat auto it = usr_to_symbol.find(def.usr); assert(it != usr_to_symbol.end()); - QueryVar& existing = vars[it->second.idx]; + optional& existing = vars[it->second.idx]; + if (!existing) + existing = QueryVar(def.usr); // Keep the existing definition if it is higher quality. - if (existing.def.definition_spelling && !def.definition_spelling) + if (existing->def.definition_spelling && !def.definition_spelling) continue; - existing.def = def; + existing->def = def; if (def.declaring_type) - UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::Var, it->second.idx, def.detailed_name); + UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Var, it->second.idx, def.detailed_name); } } @@ -773,12 +761,4 @@ void QueryDatabase::UpdateDetailedNames(size_t* qualified_name_index, SymbolKind else { detailed_names[*qualified_name_index] = name; } -} - - - - - - - -// TODO: allow user to decide some indexer choices, ie, do we mark prototype parameters as usages? +} \ No newline at end of file diff --git a/src/query.h b/src/query.h index 72e2f3b5..603a6987 100644 --- a/src/query.h +++ b/src/query.h @@ -74,11 +74,6 @@ struct SymbolIdx { bool operator<(const SymbolIdx& that) const { return kind < that.kind || idx < that.idx; } - - QueryFile* ResolveFile(QueryDatabase* db) const; - QueryType* ResolveType(QueryDatabase* db) const; - QueryFunc* ResolveFunc(QueryDatabase* db) const; - QueryVar* ResolveVar(QueryDatabase* db) const; }; struct SymbolRef { @@ -188,7 +183,6 @@ struct QueryFunc { size_t detailed_name_idx = -1; QueryFunc(const Usr& usr) : def(usr) {} - QueryFunc(const DefUpdate& def) : def(def) {} }; struct QueryVar { @@ -250,20 +244,14 @@ struct QueryDatabase { std::vector detailed_names; std::vector symbols; - // Raw data storage. - std::vector files; // File path is stored as a Usr. - std::vector types; - std::vector funcs; - std::vector vars; + // Raw data storage. Accessible via SymbolIdx instances. + std::vector> files; + std::vector> types; + std::vector> funcs; + std::vector> vars; // Lookup symbol based on a usr. spp::sparse_hash_map usr_to_symbol; - //google::dense_hash_map usr_to_symbol; - - QueryDatabase() { - //usr_to_symbol.set_empty_key(""); - } - //std::unordered_map usr_to_symbol; // Marks the given Usrs as invalid. void RemoveUsrs(const std::vector& to_remove); @@ -315,7 +303,4 @@ private: spp::sparse_hash_map cached_type_ids_; spp::sparse_hash_map cached_func_ids_; spp::sparse_hash_map cached_var_ids_; - //google::dense_hash_map> cached_type_ids_; - //google::dense_hash_map> cached_func_ids_; - //google::dense_hash_map> cached_var_ids_; };