diff --git a/src/command_line.cc b/src/command_line.cc index 7722ce36..912f0ebf 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -104,9 +104,9 @@ bool FindFileOrFail(QueryDatabase* db, 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]; - if (file) { - *out_query_file = &file.value(); + QueryFile& file = db->files[it->second.id]; + if (file.def) { + *out_query_file = &file; if (out_file_id) *out_file_id = QueryFileId(it->second.id); return true; @@ -194,25 +194,25 @@ optional FindIncludeLine(const std::vector& lines, optional GetImplementationFile(QueryDatabase* db, QueryFileId file_id, QueryFile* file) { - for (SymbolRef sym : file->def.outline) { + for (SymbolRef sym : file->def->outline) { switch (sym.idx.kind) { case SymbolKind::Func: { - optional& func = db->funcs[sym.idx.idx]; + QueryFunc& 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) { - return func->def.definition_extent->path; + if (func.def && 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]; + QueryVar& 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) { - return db->vars[sym.idx.idx]->def.definition_extent->path; + if (var.def && var.def->definition_extent && + var.def->definition_extent->path != file_id) { + return db->vars[sym.idx.idx].def->definition_extent->path; } break; } @@ -223,7 +223,7 @@ optional GetImplementationFile(QueryDatabase* db, // No associated definition, scan the project for a file in the same // directory with the same base-name. - std::string original_path = LowerPathIfCaseInsensitive(file->def.path); + std::string original_path = LowerPathIfCaseInsensitive(file->def->path); std::string target_path = original_path; size_t last = target_path.find_last_of('.'); if (last != std::string::npos) { @@ -253,18 +253,18 @@ void EnsureImplFile(QueryDatabase* db, optional& impl_uri, optional& impl_file_id) { if (!impl_uri.has_value()) { - optional& file = db->files[file_id.id]; - assert(file); + QueryFile& file = db->files[file_id.id]; + assert(file.def); - impl_file_id = GetImplementationFile(db, file_id, &file.value()); + impl_file_id = GetImplementationFile(db, file_id, &file); if (!impl_file_id.has_value()) impl_file_id = file_id; - optional& impl_file = db->files[impl_file_id->id]; - if (impl_file) - impl_uri = lsDocumentUri::FromPath(impl_file->def.path); + QueryFile& impl_file = db->files[impl_file_id->id]; + if (impl_file.def) + impl_uri = lsDocumentUri::FromPath(impl_file.def->path); else - impl_uri = lsDocumentUri::FromPath(file->def.path); + impl_uri = lsDocumentUri::FromPath(file.def->path); } } @@ -275,6 +275,7 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, QueryFileId decl_file_id, QueryFileId impl_file_id, QueryFunc& func) { + assert(func.def); for (const QueryLocation& decl : func.declarations) { if (decl.path != decl_file_id) continue; @@ -285,13 +286,12 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, optional type_name; optional same_file_insert_end; - if (func.def.declaring_type) { - optional& declaring_type = - db->types[func.def.declaring_type->id]; - if (declaring_type) { - type_name = declaring_type->def.short_name; + if (func.def->declaring_type) { + QueryType& declaring_type = db->types[func.def->declaring_type->id]; + if (declaring_type.def) { + type_name = declaring_type.def->short_name; optional ls_type_def_extent = GetLsRange( - working_file, declaring_type->def.definition_extent->range); + 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. @@ -321,21 +321,21 @@ optional BuildAutoImplementForFunction(QueryDatabase* db, best_pos.line = default_line; int best_dist = INT_MAX; - optional& file = db->files[impl_file_id.id]; - assert(file); - for (SymbolRef sym : file->def.outline) { + QueryFile& file = db->files[impl_file_id.id]; + assert(file.def); + for (SymbolRef sym : file.def->outline) { switch (sym.idx.kind) { case SymbolKind::Func: { - optional& sym_func = db->funcs[sym.idx.idx]; - if (!sym_func || !sym_func->def.definition_extent) + QueryFunc& sym_func = db->funcs[sym.idx.idx]; + if (!sym_func.def || !sym_func.def->definition_extent) break; - for (QueryLocation& func_decl : sym_func->declarations) { + for (QueryLocation& func_decl : sym_func.declarations) { 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); + db, working_files, *sym_func.def->definition_extent); if (!def_loc) continue; @@ -1486,19 +1486,19 @@ bool QueryDbMainLoop(Config* config, // Unmark all files whose timestamp has changed. CacheLoader cache_loader(config); for (const auto& file : db->files) { - if (!file) + if (!file.def) continue; optional modification_timestamp = - GetLastModificationTime(file->def.path); + GetLastModificationTime(file.def->path); if (!modification_timestamp) continue; optional cached_modification = timestamp_manager->GetLastCachedModificationTime(&cache_loader, - file->def.path); + file.def->path); if (modification_timestamp != cached_modification) - file_consumer_shared->Reset(file->def.path); + file_consumer_shared->Reset(file.def->path); } // Send index requests for every file. @@ -1524,7 +1524,7 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_CqueryTypeHierarchyTree response; response.id = msg->id; @@ -1556,7 +1556,7 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_CqueryCallTree response; response.id = msg->id; @@ -1598,18 +1598,16 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_LocationList response; response.id = msg->id; 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; + QueryType& type = db->types[ref.idx.idx]; std::vector locations = - ToQueryLocation(db, type->instances); + ToQueryLocation(db, type.instances); response.result = GetLsLocations(db, working_files, locations); } } @@ -1626,23 +1624,21 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_LocationList response; response.id = msg->id; 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; + QueryFunc& func = db->funcs[ref.idx.idx]; std::vector locations = - ToQueryLocation(db, func->callers); + ToQueryLocation(db, func.callers); for (QueryFuncRef func_ref : - GetCallersForAllBaseFunctions(db, *func)) + GetCallersForAllBaseFunctions(db, func)) locations.push_back(func_ref.loc); for (QueryFuncRef func_ref : - GetCallersForAllDerivedFunctions(db, *func)) + GetCallersForAllDerivedFunctions(db, func)) locations.push_back(func_ref.loc); response.result = GetLsLocations(db, working_files, locations); @@ -1661,25 +1657,23 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_LocationList response; response.id = msg->id; 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) + QueryType& type = db->types[ref.idx.idx]; + if (!type.def) continue; std::vector locations = - ToQueryLocation(db, type->def.parents); + ToQueryLocation(db, type.def->parents); response.result = GetLsLocations(db, working_files, locations); } else if (ref.idx.kind == SymbolKind::Func) { - optional& func = db->funcs[ref.idx.idx]; - if (!func) - continue; + QueryFunc& func = db->funcs[ref.idx.idx]; optional location = - GetBaseDefinitionOrDeclarationSpelling(db, *func); + GetBaseDefinitionOrDeclarationSpelling(db, func); if (!location) continue; optional ls_loc = @@ -1702,25 +1696,21 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_LocationList response; response.id = msg->id; 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; + QueryType& type = db->types[ref.idx.idx]; std::vector locations = - ToQueryLocation(db, type->derived); + ToQueryLocation(db, type.derived); response.result = GetLsLocations(db, working_files, locations); } else if (ref.idx.kind == SymbolKind::Func) { - optional& func = db->funcs[ref.idx.idx]; - if (!func) - continue; + QueryFunc& func = db->funcs[ref.idx.idx]; std::vector locations = - ToQueryLocation(db, func->derived); + ToQueryLocation(db, func.derived); response.result = GetLsLocations(db, working_files, locations); } } @@ -1824,7 +1814,7 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_TextDocumentRename response; response.id = msg->id; @@ -2064,7 +2054,7 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_TextDocumentDefinition response; response.id = msg->id; @@ -2126,7 +2116,7 @@ bool QueryDbMainLoop(Config* config, // No symbols - check for includes. if (response.result.empty()) { - for (const IndexInclude& include : file->def.includes) { + for (const IndexInclude& include : file->def->includes) { if (include.line == target_line) { lsLocation result; result.uri = lsDocumentUri::FromPath(include.resolved_path); @@ -2150,7 +2140,7 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_TextDocumentDocumentHighlight response; response.id = msg->id; @@ -2191,7 +2181,7 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_TextDocumentHover response; response.id = msg->id; @@ -2200,7 +2190,7 @@ bool QueryDbMainLoop(Config* config, FindSymbolsAtLocation(working_file, file, msg->params.position)) { // Found symbol. Return hover. optional ls_range = GetLsRange( - working_files->GetFileByFilename(file->def.path), ref.loc.range); + working_files->GetFileByFilename(file->def->path), ref.loc.range); if (!ls_range) continue; @@ -2222,7 +2212,7 @@ bool QueryDbMainLoop(Config* config, break; WorkingFile* working_file = - working_files->GetFileByFilename(file->def.path); + working_files->GetFileByFilename(file->def->path); Out_TextDocumentReferences response; response.id = msg->id; @@ -2266,7 +2256,7 @@ bool QueryDbMainLoop(Config* config, &file)) break; - for (SymbolRef ref : file->def.outline) { + for (SymbolRef ref : file->def->outline) { optional info = GetSymbolInfo(db, working_files, ref.idx); if (!info) @@ -2304,7 +2294,7 @@ bool QueryDbMainLoop(Config* config, << msg->params.textDocument.uri.GetPath(); break; } - for (const IndexInclude& include : file->def.includes) { + for (const IndexInclude& include : file->def->includes) { optional buffer_line; optional buffer_line_content = working_file->GetBufferLineContentFromIndexLine(include.line, @@ -2376,8 +2366,8 @@ bool QueryDbMainLoop(Config* config, for (SymbolRef sym : syms) { switch (sym.idx.kind) { case SymbolKind::Type: { - optional& type = db->types[sym.idx.idx]; - if (!type) + QueryType& type = db->types[sym.idx.idx]; + if (!type.def) break; int num_edits = 0; @@ -2385,16 +2375,16 @@ bool QueryDbMainLoop(Config* config, // Get implementation file. Out_TextDocumentCodeAction::Command command; - for (QueryFuncId func_id : type->def.funcs) { - optional& func_def = db->funcs[func_id.id]; - if (!func_def || func_def->def.definition_extent) + for (QueryFuncId func_id : type.def->funcs) { + QueryFunc& func_def = db->funcs[func_id.id]; + if (!func_def.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); + *impl_file_id, func_def); if (!edit) continue; @@ -2423,15 +2413,15 @@ bool QueryDbMainLoop(Config* config, command.arguments.textDocumentUri = *impl_uri; command.title = "Auto-Implement " + std::to_string(num_edits) + - " methods on " + type->def.short_name; + " methods on " + type.def->short_name; command.command = "cquery._autoImplement"; response.result.push_back(command); break; } case SymbolKind::Func: { - optional& func = db->funcs[sym.idx.idx]; - if (!func || func->def.definition_extent) + QueryFunc& func = db->funcs[sym.idx.idx]; + if (!func.def || func.def->definition_extent) break; EnsureImplFile(db, file_id, impl_uri /*out*/, @@ -2439,12 +2429,12 @@ bool QueryDbMainLoop(Config* config, // Get implementation file. Out_TextDocumentCodeAction::Command command; - command.title = "Auto-Implement " + func->def.short_name; + 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); + *impl_file_id, func); if (!edit) break; @@ -2496,11 +2486,11 @@ bool QueryDbMainLoop(Config* config, if (!decl_file_id) continue; - optional& decl_file = db->files[decl_file_id->id]; - if (!decl_file) + QueryFile& decl_file = db->files[decl_file_id->id]; + if (!decl_file.def) continue; - include_absolute_paths.insert(decl_file->def.path); + include_absolute_paths.insert(decl_file.def->path); } // Build include strings. @@ -2591,50 +2581,50 @@ bool QueryDbMainLoop(Config* config, common.result = &response.result; common.db = db; common.working_files = working_files; - common.working_file = working_files->GetFileByFilename(file->def.path); + common.working_file = working_files->GetFileByFilename(file->def->path); - for (SymbolRef ref : file->def.outline) { + for (SymbolRef ref : file->def->outline) { // NOTE: We OffsetColumn so that the code lens always show up in a // predictable order. Otherwise, the client may randomize it. SymbolIdx symbol = ref.idx; switch (symbol.kind) { case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (!type) + QueryType& type = db->types[symbol.idx]; + if (!type.def) continue; AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), - type->uses, type->def.definition_spelling, + type.uses, type.def->definition_spelling, true /*force_display*/); AddCodeLens("derived", "derived", &common, ref.loc.OffsetStartColumn(1), - ToQueryLocation(db, type->derived), nullopt, + ToQueryLocation(db, type.derived), nullopt, false /*force_display*/); AddCodeLens("var", "vars", &common, ref.loc.OffsetStartColumn(2), - ToQueryLocation(db, type->instances), nullopt, + ToQueryLocation(db, type.instances), nullopt, false /*force_display*/); break; } case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (!func) + QueryFunc& func = db->funcs[symbol.idx]; + if (!func.def) continue; int16_t offset = 0; std::vector base_callers = - GetCallersForAllBaseFunctions(db, *func); + GetCallersForAllBaseFunctions(db, func); std::vector derived_callers = - GetCallersForAllDerivedFunctions(db, *func); + GetCallersForAllDerivedFunctions(db, func); if (base_callers.empty() && derived_callers.empty()) { AddCodeLens("call", "calls", &common, ref.loc.OffsetStartColumn(offset++), - ToQueryLocation(db, func->callers), nullopt, + ToQueryLocation(db, func.callers), nullopt, true /*force_display*/); } else { AddCodeLens("direct call", "direct calls", &common, ref.loc.OffsetStartColumn(offset++), - ToQueryLocation(db, func->callers), nullopt, + ToQueryLocation(db, func.callers), nullopt, false /*force_display*/); if (!base_callers.empty()) AddCodeLens("base call", "base calls", &common, @@ -2650,12 +2640,12 @@ bool QueryDbMainLoop(Config* config, AddCodeLens("derived", "derived", &common, ref.loc.OffsetStartColumn(offset++), - ToQueryLocation(db, func->derived), nullopt, + ToQueryLocation(db, func.derived), nullopt, false /*force_display*/); // "Base" optional base_loc = - GetBaseDefinitionOrDeclarationSpelling(db, *func); + GetBaseDefinitionOrDeclarationSpelling(db, func); if (base_loc) { optional ls_base = GetLsLocation(db, working_files, *base_loc); @@ -2680,21 +2670,21 @@ bool QueryDbMainLoop(Config* config, break; } case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (!var) + QueryVar& var = db->vars[symbol.idx]; + if (!var.def) continue; - if (var->def.is_local && !config->codeLensOnLocalVariables) + 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) + if (var.def->is_macro) force_display = false; AddCodeLens("ref", "refs", &common, ref.loc.OffsetStartColumn(0), - var->uses, var->def.definition_spelling, + var.uses, var.def->definition_spelling, force_display); break; } diff --git a/src/query.cc b/src/query.cc index 4bf7ca7f..69604202 100644 --- a/src/query.cc +++ b/src/query.cc @@ -6,7 +6,6 @@ #include #include - #include #include #include @@ -15,7 +14,6 @@ #include #include - // TODO: Make all copy constructors explicit. namespace { @@ -665,22 +663,22 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind, switch (usr_kind) { case SymbolKind::File: { for (const Usr& usr : to_remove) - files[usr_to_file[LowerPathIfCaseInsensitive(usr)].id] = nullopt; + files[usr_to_file[LowerPathIfCaseInsensitive(usr)].id].def = nullopt; break; } case SymbolKind::Type: { for (const Usr& usr : to_remove) - types[usr_to_type[usr].id] = nullopt; + types[usr_to_type[usr].id].def = nullopt; break; } case SymbolKind::Func: { for (const Usr& usr : to_remove) - funcs[usr_to_func[usr].id] = nullopt; + funcs[usr_to_func[usr].id].def = nullopt; break; } case SymbolKind::Var: { for (const Usr& usr : to_remove) - vars[usr_to_var[usr].id] = nullopt; + vars[usr_to_var[usr].id].def = nullopt; break; } case SymbolKind::Invalid: @@ -696,13 +694,11 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) { // 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); \ +#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]; \ + AddRange(&def.def_var_name, merge_update.to_add); \ + RemoveRange(&def.def_var_name, merge_update.to_remove); \ } RemoveUsrs(SymbolKind::File, update->files_removed); @@ -735,12 +731,10 @@ void QueryDatabase::ImportOrUpdate( auto it = usr_to_file.find(LowerPathIfCaseInsensitive(def.path)); assert(it != usr_to_file.end()); - optional& existing = files[it->second.id]; - if (!existing) - existing = QueryFile(def.path); + QueryFile& existing = files[it->second.id]; - existing->def = def; - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::File, + existing.def = def; + UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::File, it->second.id, def.path); } } @@ -756,16 +750,15 @@ void QueryDatabase::ImportOrUpdate( assert(it != usr_to_type.end()); assert(it->second.id >= 0 && it->second.id < types.size()); - optional& existing = types[it->second.id]; - if (!existing) - existing = QueryType(def.usr); + QueryType& existing = types[it->second.id]; // Keep the existing definition if it is higher quality. - if (existing->def.definition_spelling && !def.definition_spelling) + if (existing.def && existing.def->definition_spelling && + !def.definition_spelling) continue; - existing->def = def; - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Type, + existing.def = def; + UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::Type, it->second.id, def.detailed_name); } } @@ -781,16 +774,15 @@ void QueryDatabase::ImportOrUpdate( assert(it != usr_to_func.end()); assert(it->second.id >= 0 && it->second.id < funcs.size()); - optional& existing = funcs[it->second.id]; - if (!existing) - existing = QueryFunc(def.usr); + QueryFunc& existing = funcs[it->second.id]; // Keep the existing definition if it is higher quality. - if (existing->def.definition_spelling && !def.definition_spelling) + if (existing.def && existing.def->definition_spelling && + !def.definition_spelling) continue; - existing->def = def; - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Func, + existing.def = def; + UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::Func, it->second.id, def.detailed_name); } } @@ -806,17 +798,16 @@ void QueryDatabase::ImportOrUpdate( assert(it != usr_to_var.end()); assert(it->second.id >= 0 && it->second.id < vars.size()); - optional& existing = vars[it->second.id]; - if (!existing) - existing = QueryVar(def.usr); + QueryVar& existing = vars[it->second.id]; // Keep the existing definition if it is higher quality. - if (existing->def.definition_spelling && !def.definition_spelling) + if (existing.def && existing.def->definition_spelling && + !def.definition_spelling) continue; - existing->def = def; + existing.def = def; if (!def.is_local) - UpdateDetailedNames(&existing->detailed_name_idx, SymbolKind::Var, + UpdateDetailedNames(&existing.detailed_name_idx, SymbolKind::Var, it->second.id, def.detailed_name); } } @@ -952,14 +943,14 @@ TEST_CASE("apply delta") { &previous_map, ¤t_map, &previous, ¤t); db.ApplyIndexUpdate(&import_update); - REQUIRE(db.funcs[0]->callers.size() == 2); - REQUIRE(db.funcs[0]->callers[0].loc.range == Range(Position(1, 0))); - REQUIRE(db.funcs[0]->callers[1].loc.range == Range(Position(2, 0))); + REQUIRE(db.funcs[0].callers.size() == 2); + REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(1, 0))); + REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(2, 0))); db.ApplyIndexUpdate(&delta_update); - REQUIRE(db.funcs[0]->callers.size() == 2); - REQUIRE(db.funcs[0]->callers[0].loc.range == Range(Position(4, 0))); - REQUIRE(db.funcs[0]->callers[1].loc.range == Range(Position(5, 0))); + REQUIRE(db.funcs[0].callers.size() == 2); + REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(4, 0))); + REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(5, 0))); } TEST_SUITE_END(); \ No newline at end of file diff --git a/src/query.h b/src/query.h index 8edd865b..ccc6bb4a 100644 --- a/src/query.h +++ b/src/query.h @@ -169,10 +169,13 @@ struct QueryFile { using DefUpdate = Def; - DefUpdate def; + optional def; size_t detailed_name_idx = (size_t)-1; - QueryFile(const std::string& path) { def.path = path; } + QueryFile(const std::string& path) { + def = DefUpdate(); + def->path = path; + } }; MAKE_REFLECT_STRUCT(QueryFile::Def, path, outline, all_symbols); @@ -185,7 +188,7 @@ struct QueryType { using InstancesUpdate = MergeableUpdate; using UsesUpdate = MergeableUpdate; - DefUpdate def; + optional def; std::vector derived; std::vector instances; std::vector uses; @@ -204,7 +207,7 @@ struct QueryFunc { using DerivedUpdate = MergeableUpdate; using CallersUpdate = MergeableUpdate; - DefUpdate def; + optional def; std::vector declarations; std::vector derived; std::vector callers; @@ -218,7 +221,7 @@ struct QueryVar { VarDefDefinitionData; using UsesUpdate = MergeableUpdate; - DefUpdate def; + optional def; std::vector uses; size_t detailed_name_idx = (size_t)-1; @@ -298,10 +301,10 @@ struct QueryDatabase { std::vector symbols; // Raw data storage. Accessible via SymbolIdx instances. - std::vector> files; - std::vector> types; - std::vector> funcs; - std::vector> vars; + std::vector files; + std::vector types; + std::vector funcs; + std::vector vars; // Lookup symbol based on a usr. // NOTE: For usr_to_file make sure to call LowerPathIfCaseInsensitive on key. diff --git a/src/query_utils.cc b/src/query_utils.cc index 14150cde..3ea72139 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -15,25 +15,25 @@ int ComputeRangeSize(const Range& range) { optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryTypeId& id) { - optional& type = db->types[id.id]; - if (type) - return type->def.definition_spelling; + QueryType& type = db->types[id.id]; + if (type.def) + return type.def->definition_spelling; return nullopt; } optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryFuncId& id) { - optional& func = db->funcs[id.id]; - if (func) - return func->def.definition_spelling; + QueryFunc& func = db->funcs[id.id]; + if (func.def) + return func.def->definition_spelling; return nullopt; } optional GetDefinitionSpellingOfSymbol(QueryDatabase* db, const QueryVarId& id) { - optional& var = db->vars[id.id]; - if (var) - return var->def.definition_spelling; + QueryVar& var = db->vars[id.id]; + if (var.def) + return var.def->definition_spelling; return nullopt; } @@ -41,21 +41,21 @@ 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; + QueryType& type = db->types[symbol.idx]; + if (type.def) + return type.def->definition_spelling; break; } case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) - return func->def.definition_spelling; + QueryFunc& func = db->funcs[symbol.idx]; + if (func.def) + return func.def->definition_spelling; break; } case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->def.definition_spelling; + QueryVar& var = db->vars[symbol.idx]; + if (var.def) + return var.def->definition_spelling; break; } case SymbolKind::File: @@ -71,21 +71,21 @@ 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; + QueryType& type = db->types[symbol.idx]; + if (type.def) + return type.def->definition_extent; break; } case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) - return func->def.definition_extent; + QueryFunc& func = db->funcs[symbol.idx]; + if (func.def) + return func.def->definition_extent; break; } case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->def.definition_extent; + QueryVar& var = db->vars[symbol.idx]; + if (var.def) + return var.def->definition_extent; break; } case SymbolKind::File: { @@ -103,21 +103,21 @@ optional GetDefinitionExtentOfSymbol(QueryDatabase* db, 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; + QueryType& type = db->types[symbol.idx]; + if (type.def) + return type.def->detailed_name; break; } case SymbolKind::Func: { - optional& func = db->funcs[symbol.idx]; - if (func) - return func->def.detailed_name; + QueryFunc& func = db->funcs[symbol.idx]; + if (func.def) + return func.def->detailed_name; break; } case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->def.detailed_name; + QueryVar& var = db->vars[symbol.idx]; + if (var.def) + return var.def->detailed_name; break; } case SymbolKind::File: @@ -133,25 +133,23 @@ 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; + QueryType& type = db->types[symbol.idx]; + if (type.def && 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; - } + QueryFunc& func = db->funcs[symbol.idx]; + if (!func.declarations.empty()) + return func.declarations[0].path; + if (func.def && 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; + QueryVar& var = db->vars[symbol.idx]; + if (var.def && var.def->definition_spelling) + return var.def->definition_spelling->path; break; } case SymbolKind::File: { @@ -214,28 +212,21 @@ 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; + QueryType& type = db->types[symbol.idx]; + return type.uses; } 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; + QueryFunc& func = db->funcs[symbol.idx]; + std::vector result = ToQueryLocation(db, func.callers); + AddRange(&result, func.declarations); + if (func.def && func.def->definition_spelling) + result.push_back(*func.def->definition_spelling); + return result; } case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) - return var->uses; - break; + QueryVar& var = db->vars[symbol.idx]; + return var.uses; } case SymbolKind::File: case SymbolKind::Invalid: { @@ -255,24 +246,22 @@ std::vector GetDeclarationsOfSymbolForGotoDefinition( // 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; + QueryType& type = db->types[symbol.idx]; + if (type.def) { + 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; + QueryFunc& func = db->funcs[symbol.idx]; + return func.declarations; } case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (var) { - optional declaration = var->def.declaration; + QueryVar& var = db->vars[symbol.idx]; + if (var.def) { + optional declaration = var.def->declaration; if (declaration) return {*declaration}; } @@ -288,15 +277,15 @@ std::vector GetDeclarationsOfSymbolForGotoDefinition( optional GetBaseDefinitionOrDeclarationSpelling( QueryDatabase* db, QueryFunc& func) { - if (!func.def.base) - return nullopt; - optional& base = db->funcs[func.def.base->id]; - if (!base) + 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 def; + if (base.def) + def = base.def->definition_spelling; + if (!def && !base.declarations.empty()) + def = base.declarations[0]; return def; } @@ -306,28 +295,25 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { return true; // Check for base calls. - optional func_id = root.def.base; + optional func_id = root.def->base; while (func_id) { - optional& func = db->funcs[func_id->id]; - if (!func) - break; - if (!func->callers.empty()) + QueryFunc& func = db->funcs[func_id->id]; + if (!func.callers.empty()) return true; - func_id = func->def.base; + if (!func.def) + break; + func_id = func.def->base; } // Check for derived calls. std::queue queue; PushRange(&queue, root.derived); while (!queue.empty()) { - optional& func = db->funcs[queue.front().id]; + QueryFunc& func = db->funcs[queue.front().id]; queue.pop(); - if (!func) - continue; - - if (!func->derived.empty()) + if (!func.callers.empty()) return true; - PushRange(&queue, func->derived); + PushRange(&queue, func.derived); } return false; @@ -337,14 +323,14 @@ std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, QueryFunc& root) { std::vector callers; - optional func_id = root.def.base; + optional func_id = root.def->base; while (func_id) { - optional& func = db->funcs[func_id->id]; - if (!func) - break; + QueryFunc& func = db->funcs[func_id->id]; + AddRange(&callers, func.callers); - AddRange(&callers, func->callers); - func_id = func->def.base; + if (!func.def) + break; + func_id = func.def->base; } return callers; @@ -358,13 +344,11 @@ std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, PushRange(&queue, root.derived); while (!queue.empty()) { - optional& func = db->funcs[queue.front().id]; + QueryFunc& func = db->funcs[queue.front().id]; queue.pop(); - if (!func) - continue; - PushRange(&queue, func->derived); - AddRange(&callers, func->callers); + PushRange(&queue, func.derived); + AddRange(&callers, func.callers); } return callers; @@ -412,9 +396,9 @@ optional GetLsRange(WorkingFile* working_file, const Range& location) { lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id, std::string* path) { - optional& file = db->files[file_id.id]; - if (file) { - *path = file->def.path; + QueryFile& file = db->files[file_id.id]; + if (file.def) { + *path = file.def->path; return lsDocumentUri::FromPath(*path); } else { *path = ""; @@ -423,9 +407,9 @@ lsDocumentUri GetLsDocumentUri(QueryDatabase* db, } lsDocumentUri GetLsDocumentUri(QueryDatabase* db, QueryFileId file_id) { - optional& file = db->files[file_id.id]; - if (file) { - return lsDocumentUri::FromPath(file->def.path); + QueryFile& file = db->files[file_id.id]; + if (file.def) { + return lsDocumentUri::FromPath(file.def->path); } else { return lsDocumentUri::FromPath(""); } @@ -468,54 +452,54 @@ optional GetSymbolInfo(QueryDatabase* db, SymbolIdx symbol) { switch (symbol.kind) { case SymbolKind::File: { - optional& file = db->files[symbol.idx]; - if (!file) + QueryFile& file = db->files[symbol.idx]; + if (!file.def) return nullopt; lsSymbolInformation info; - info.name = file->def.path; + info.name = file.def->path; info.kind = lsSymbolKind::File; return info; } case SymbolKind::Type: { - optional& type = db->types[symbol.idx]; - if (!type) + QueryType& type = db->types[symbol.idx]; + if (!type.def) 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.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) + QueryFunc& func = db->funcs[symbol.idx]; + if (!func.def) return nullopt; lsSymbolInformation info; - info.name = func->def.short_name; - info.containerName = func->def.detailed_name; + 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) + if (func.def->declaring_type.has_value()) { + QueryType& container = + db->types[func.def->declaring_type->id]; + if (container.def) info.kind = lsSymbolKind::Method; } return info; } case SymbolKind::Var: { - optional& var = db->vars[symbol.idx]; - if (!var) + QueryVar& var = db->vars[symbol.idx]; + if (!var.def) return nullopt; lsSymbolInformation info; - info.name += var->def.short_name; - info.containerName = var->def.detailed_name; + info.name += var.def->short_name; + info.containerName = var.def->detailed_name; info.kind = lsSymbolKind::Variable; return info; } @@ -585,11 +569,11 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, if (path_to_edit.find(location.path) == path_to_edit.end()) { path_to_edit[location.path] = lsTextDocumentEdit(); - optional& file = db->files[location.path.id]; - if (!file) + QueryFile& file = db->files[location.path.id]; + if (!file.def) continue; - const std::string& path = file->def.path; + const std::string& path = file.def->path; path_to_edit[location.path].textDocument.uri = lsDocumentUri::FromPath(path); @@ -630,7 +614,7 @@ std::vector FindSymbolsAtLocation(WorkingFile* working_file, target_line = *index_line; } - for (const SymbolRef& ref : file->def.all_symbols) { + for (const SymbolRef& ref : file->def->all_symbols) { if (ref.loc.range.Contains(target_line, target_column)) symbols.push_back(ref); } @@ -660,23 +644,23 @@ NonElidedVector BuildParentInheritanceHierarchyForType(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) { - optional& root_type = db->types[root.id]; - if (!root_type) + QueryType& root_type = db->types[root.id]; + if (!root_type.def) return {}; NonElidedVector parent_entries; - parent_entries.reserve(root_type->def.parents.size()); + parent_entries.reserve(root_type.def->parents.size()); - for (QueryTypeId parent_id : root_type->def.parents) { - optional& parent_type = db->types[parent_id.id]; - if (!parent_type) + for (QueryTypeId parent_id : root_type.def->parents) { + QueryType& parent_type = db->types[parent_id.id]; + if (!parent_type.def) continue; Out_CqueryTypeHierarchyTree::TypeEntry parent_entry; - parent_entry.name = parent_type->def.detailed_name; - if (parent_type->def.definition_spelling) + 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); + db, working_files, *parent_type.def->definition_spelling); parent_entry.children = BuildParentInheritanceHierarchyForType(db, working_files, parent_id); @@ -690,19 +674,19 @@ optional BuildInheritanceHierarchyForType(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root_id) { - optional& root_type = db->types[root_id.id]; - if (!root_type) + QueryType& root_type = db->types[root_id.id]; + if (!root_type.def) return nullopt; Out_CqueryTypeHierarchyTree::TypeEntry entry; // Name and location. - entry.name = root_type->def.detailed_name; - if (root_type->def.definition_spelling) + entry.name = root_type.def->detailed_name; + if (root_type.def->definition_spelling) entry.location = - GetLsLocation(db, working_files, *root_type->def.definition_spelling); + GetLsLocation(db, working_files, *root_type.def->definition_spelling); - entry.children.reserve(root_type->derived.size()); + entry.children.reserve(root_type.derived.size()); // Base types. Out_CqueryTypeHierarchyTree::TypeEntry base; @@ -714,7 +698,7 @@ BuildInheritanceHierarchyForType(QueryDatabase* db, entry.children.push_back(base); // Add derived. - for (QueryTypeId derived : root_type->derived) { + for (QueryTypeId derived : root_type.derived) { auto derived_entry = BuildInheritanceHierarchyForType(db, working_files, derived); if (derived_entry) @@ -728,21 +712,21 @@ NonElidedVector BuildParentInheritanceHierarchyForFunc(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root) { - optional& root_func = db->funcs[root.id]; - if (!root_func || !root_func->def.base) + QueryFunc& root_func = db->funcs[root.id]; + if (!root_func.def || !root_func.def->base) return {}; - optional& parent_func = db->funcs[root_func->def.base->id]; - if (!parent_func) + QueryFunc& parent_func = db->funcs[root_func.def->base->id]; + if (!parent_func.def) return {}; Out_CqueryTypeHierarchyTree::TypeEntry parent_entry; - parent_entry.name = parent_func->def.detailed_name; - if (parent_func->def.definition_spelling) + 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); + GetLsLocation(db, working_files, *parent_func.def->definition_spelling); parent_entry.children = BuildParentInheritanceHierarchyForFunc( - db, working_files, *root_func->def.base); + db, working_files, *root_func.def->base); NonElidedVector entries; entries.push_back(parent_entry); @@ -753,19 +737,19 @@ optional BuildInheritanceHierarchyForFunc(QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root_id) { - optional& root_func = db->funcs[root_id.id]; - if (!root_func) + QueryFunc& root_func = db->funcs[root_id.id]; + if (!root_func.def) return nullopt; Out_CqueryTypeHierarchyTree::TypeEntry entry; // Name and location. - entry.name = root_func->def.detailed_name; - if (root_func->def.definition_spelling) + entry.name = root_func.def->detailed_name; + if (root_func.def->definition_spelling) entry.location = - GetLsLocation(db, working_files, *root_func->def.definition_spelling); + GetLsLocation(db, working_files, *root_func.def->definition_spelling); - entry.children.reserve(root_func->derived.size()); + entry.children.reserve(root_func.derived.size()); // Base types. Out_CqueryTypeHierarchyTree::TypeEntry base; @@ -777,7 +761,7 @@ BuildInheritanceHierarchyForFunc(QueryDatabase* db, entry.children.push_back(base); // Add derived. - for (QueryFuncId derived : root_func->derived) { + for (QueryFuncId derived : root_func.derived) { auto derived_entry = BuildInheritanceHierarchyForFunc(db, working_files, derived); if (derived_entry) @@ -791,21 +775,19 @@ 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) + QueryFunc& root_func = db->funcs[root.id]; + if (!root_func.def || !root_func.def->definition_spelling) return {}; optional def_loc = - GetLsLocation(db, working_files, *root_func->def.definition_spelling); + GetLsLocation(db, working_files, *root_func.def->definition_spelling); if (!def_loc) return {}; Out_CqueryCallTree::CallEntry entry; - entry.name = root_func->def.short_name; - entry.usr = root_func->def.usr; + entry.name = root_func.def->short_name; + entry.usr = root_func.def->usr; entry.location = *def_loc; - entry.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, *root_func); + entry.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, root_func); NonElidedVector result; result.push_back(entry); return result; @@ -815,8 +797,8 @@ NonElidedVector BuildExpandCallTree( QueryDatabase* db, WorkingFiles* working_files, QueryFuncId root) { - optional& root_func = db->funcs[root.id]; - if (!root_func) + QueryFunc& root_func = db->funcs[root.id]; + if (!root_func.def) return {}; auto format_location = @@ -825,9 +807,9 @@ NonElidedVector BuildExpandCallTree( std::string base; if (declaring_type) { - optional type = db->types[declaring_type->id]; - if (type) - base = type->def.detailed_name; + QueryType type = db->types[declaring_type->id]; + if (type.def) + base = type.def->detailed_name; } if (base.empty()) { @@ -869,17 +851,17 @@ NonElidedVector BuildExpandCallTree( } if (caller.has_id()) { - optional& call_func = db->funcs[caller.id_.id]; - if (!call_func) + QueryFunc& call_func = db->funcs[caller.id_.id]; + if (!call_func.def) 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.usr = call_func->def.usr; + 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.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, call_func); call_entry.callType = call_type; result.push_back(call_entry); } else { @@ -896,13 +878,13 @@ NonElidedVector BuildExpandCallTree( }; std::vector base_callers = - GetCallersForAllBaseFunctions(db, *root_func); + GetCallersForAllBaseFunctions(db, root_func); std::vector derived_callers = - GetCallersForAllDerivedFunctions(db, *root_func); - result.reserve(root_func->callers.size() + base_callers.size() + + GetCallersForAllDerivedFunctions(db, root_func); + result.reserve(root_func.callers.size() + base_callers.size() + derived_callers.size()); - for (QueryFuncRef caller : root_func->callers) + for (QueryFuncRef caller : root_func.callers) handle_caller(caller, Out_CqueryCallTree::CallType::Direct); for (QueryFuncRef caller : base_callers) { // Do not show calls to the base function coming from this function.