diff --git a/src/indexer.cc b/src/indexer.cc index 19eeacc6..9835d029 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -685,7 +685,6 @@ const int IndexFile::kMinorVersion = 0; IndexFile::IndexFile(const std::string& path, const std::string& contents) : id_cache(path), path(path), file_contents(contents) {} -// TODO: Optimize for const char*? IndexTypeId IndexFile::ToTypeId(Usr usr) { auto it = id_cache.usr_to_type_id.find(usr); if (it != id_cache.usr_to_type_id.end()) @@ -1358,7 +1357,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, sem_parent, Role::Definition); ref_type->def.extent = SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None); -#if CINDEX_HAVE_PRETTY +#if 0&&CINDEX_HAVE_PRETTY ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor); #else ref_type->def.detailed_name = ref_cursor.get_spell_name(); @@ -1392,7 +1391,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, sem_parent, Role::Definition); ref_type->def.extent = SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None); -#if CINDEX_HAVE_PRETTY +#if 0&&CINDEX_HAVE_PRETTY + // template void f(T t){} // weird, the name is empty ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor); #else ref_type->def.detailed_name = ref_cursor.get_spell_name(); diff --git a/src/messages/cquery_member_hierarchy.cc b/src/messages/cquery_member_hierarchy.cc index 9254b004..477d13ac 100644 --- a/src/messages/cquery_member_hierarchy.cc +++ b/src/messages/cquery_member_hierarchy.cc @@ -61,7 +61,7 @@ ExpandNode(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) { return {}; std::vector ret; - EachWithGen(db->vars, def->vars, [&](QueryVar& var) { + EachDefinedEntity(db->vars, def->vars, [&](QueryVar& var) { const QueryVar::Def* def1 = var.AnyDef(); Out_CqueryMemberHierarchy::Entry entry; entry.name = def1->ShortName(); diff --git a/src/messages/cquery_type_hierarchy_tree.cc b/src/messages/cquery_type_hierarchy_tree.cc index 782465b9..4f4376fe 100644 --- a/src/messages/cquery_type_hierarchy_tree.cc +++ b/src/messages/cquery_type_hierarchy_tree.cc @@ -35,7 +35,7 @@ BuildParentInheritanceHierarchyForType(QueryDatabase* db, const QueryType::Def* def = root_type.AnyDef(); parent_entries.reserve(def->parents.size()); - EachWithGen(db->types, def->parents, [&](QueryType& parent_type) { + EachDefinedEntity(db->types, def->parents, [&](QueryType& parent_type) { Out_CqueryTypeHierarchyTree::TypeEntry parent_entry; const QueryType::Def* def1 = parent_type.AnyDef(); parent_entry.name = def1->detailed_name.c_str(); @@ -74,7 +74,7 @@ BuildInheritanceHierarchyForType(QueryDatabase* db, entry.children.push_back(base); // Add derived. - EachWithGen(db->types, root_type.derived, [&](QueryType& type) { + EachDefinedEntity(db->types, root_type.derived, [&](QueryType& type) { auto derived_entry = BuildInheritanceHierarchyForType(db, working_files, type); if (derived_entry) diff --git a/src/messages/text_document_code_action.cc b/src/messages/text_document_code_action.cc index ee01a377..a2d7f139 100644 --- a/src/messages/text_document_code_action.cc +++ b/src/messages/text_document_code_action.cc @@ -359,7 +359,7 @@ struct TextDocumentCodeActionHandler // Get implementation file. Out_TextDocumentCodeAction::Command command; - EachWithGen(db->funcs, def->funcs, [&](QueryFunc& func_def) { + EachDefinedEntity(db->funcs, def->funcs, [&](QueryFunc& func_def) { const QueryFunc::Def* def1 = func_def.AnyDef(); if (def1->extent) return; diff --git a/src/messages/text_document_definition.cc b/src/messages/text_document_definition.cc index 6773f0c9..907013bf 100644 --- a/src/messages/text_document_definition.cc +++ b/src/messages/text_document_definition.cc @@ -81,7 +81,7 @@ struct TextDocumentDefinitionHandler // - start at spelling but end at extent for better mouse tooltip // - goto declaration while in definition of recursive type std::vector uses; - EachDef(db, sym, [&](const auto& def) { + EachEntityDef(db, sym, [&](const auto& def) { if (def.spell && def.extent) { Use spell = *def.spell; // If on a definition, clear |uses| to find declarations below. diff --git a/src/messages/text_document_document_highlight.cc b/src/messages/text_document_document_highlight.cc index 2450acab..3f6609c7 100644 --- a/src/messages/text_document_document_highlight.cc +++ b/src/messages/text_document_document_highlight.cc @@ -39,28 +39,23 @@ struct TextDocumentDocumentHighlightHandler for (SymbolRef sym : FindSymbolsAtLocation(working_file, file, request->params.position)) { // Found symbol. Return references to highlight. - std::vector uses = GetUsesOfSymbol(db, sym, true); - out.result.reserve(uses.size()); - for (Use use : uses) { + EachUse(db, sym, true, [&](Use use) { if (use.file != file_id) - continue; - - optional ls_location = - GetLsLocation(db, working_files, use); - if (!ls_location) - continue; - - lsDocumentHighlight highlight; - highlight.range = ls_location->range; - if (use.role & Role::Write) - highlight.kind = lsDocumentHighlightKind::Write; - else if (use.role & Role::Read) - highlight.kind = lsDocumentHighlightKind::Read; - else - highlight.kind = lsDocumentHighlightKind::Text; - highlight.role = use.role; - out.result.push_back(highlight); - } + return; + if (optional ls_loc = + GetLsLocation(db, working_files, use)) { + lsDocumentHighlight highlight; + highlight.range = ls_loc->range; + if (use.role & Role::Write) + highlight.kind = lsDocumentHighlightKind::Write; + else if (use.role & Role::Read) + highlight.kind = lsDocumentHighlightKind::Read; + else + highlight.kind = lsDocumentHighlightKind::Text; + highlight.role = use.role; + out.result.push_back(highlight); + } + }); break; } diff --git a/src/messages/text_document_references.cc b/src/messages/text_document_references.cc index f39751a6..14c1c3ce 100644 --- a/src/messages/text_document_references.cc +++ b/src/messages/text_document_references.cc @@ -54,16 +54,13 @@ struct TextDocumentReferencesHandler for (const SymbolRef& sym : FindSymbolsAtLocation(working_file, file, request->params.position)) { // Found symbol. Return references. - std::vector uses = GetUsesOfSymbol( - db, sym, request->params.context.includeDeclaration); - out.result.reserve(uses.size()); - for (Use use : uses) { - optional ls_loc = GetLsLocationEx( - db, working_files, use, config->extension.referenceContainer); - if (ls_loc) { - out.result.push_back(*ls_loc); - } - } + EachUse(db, sym, request->params.context.includeDeclaration, + [&](Use use) { + if (optional ls_loc = + GetLsLocationEx(db, working_files, use, + config->extension.referenceContainer)) + out.result.push_back(*ls_loc); + }); break; } diff --git a/src/messages/text_document_rename.cc b/src/messages/text_document_rename.cc index 92a83755..ecc54cf8 100644 --- a/src/messages/text_document_rename.cc +++ b/src/messages/text_document_rename.cc @@ -6,15 +6,14 @@ namespace { lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, WorkingFiles* working_files, - const std::vector& uses, + SymbolRef sym, const std::string& new_text) { std::unordered_map path_to_edit; - for (Use use : uses) { - optional ls_location = - GetLsLocation(db, working_files, use); + EachUse(db, sym, true, [&](Use use) { + optional ls_location = GetLsLocation(db, working_files, use); if (!ls_location) - continue; + return; QueryFileId file_id = use.file; if (path_to_edit.find(file_id) == path_to_edit.end()) { @@ -22,16 +21,14 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, QueryFile& file = db->files[file_id.id]; if (!file.def) - continue; + return; const std::string& path = file.def->path; - path_to_edit[file_id].textDocument.uri = - lsDocumentUri::FromPath(path); + path_to_edit[file_id].textDocument.uri = lsDocumentUri::FromPath(path); WorkingFile* working_file = working_files->GetFileByFilename(path); if (working_file) - path_to_edit[file_id].textDocument.version = - working_file->version; + path_to_edit[file_id].textDocument.version = working_file->version; } lsTextEdit edit; @@ -42,7 +39,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db, auto& edits = path_to_edit[file_id].edits; if (std::find(edits.begin(), edits.end(), edit) == edits.end()) edits.push_back(edit); - } + }); lsWorkspaceEdit edit; for (const auto& changes : path_to_edit) @@ -98,9 +95,8 @@ struct TextDocumentRenameHandler : BaseMessageHandler { for (SymbolRef sym : FindSymbolsAtLocation(working_file, file, request->params.position)) { // Found symbol. Return references to rename. - out.result = BuildWorkspaceEdit(db, working_files, - GetUsesOfSymbol(db, sym, true), - request->params.newName); + out.result = + BuildWorkspaceEdit(db, working_files, sym, request->params.newName); break; } diff --git a/src/query_utils.cc b/src/query_utils.cc index f0719992..730e3c5d 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -6,6 +6,7 @@ #include #include +#include namespace { @@ -40,63 +41,19 @@ std::vector ToUsesHelper(std::vector& entities, Maybe GetDefinitionSpellingOfSymbol(QueryDatabase* db, SymbolIdx sym) { - switch (sym.kind) { - case SymbolKind::File: - break; - case SymbolKind::Func: { - for (auto& def : db->GetFunc(sym).def) - if (def.spell) - return def.spell; - break; - } - case SymbolKind::Type: { - for (auto& def : db->GetType(sym).def) - if (def.spell) - return def.spell; - break; - } - case SymbolKind::Var: { - for (auto& def : db->GetVar(sym).def) - if (def.spell) - return def.spell; - break; - } - case SymbolKind::Invalid: - assert(false && "unexpected"); - break; - } - return nullopt; + Maybe ret; + EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.spell); }); + return ret; } Maybe GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym) { - switch (sym.kind) { - case SymbolKind::File: - return Use(Range(Position(0, 0), Position(0, 0)), sym.id, sym.kind, - Role::None, QueryFileId(sym.id)); - case SymbolKind::Func: { - for (auto& def : db->GetFunc(sym).def) - if (def.extent) - return def.extent; - break; - } - case SymbolKind::Type: { - for (auto& def : db->GetType(sym).def) - if (def.extent) - return def.extent; - break; - } - case SymbolKind::Var: { - for (auto& def : db->GetVar(sym).def) - if (def.extent) - return def.extent; - break; - } - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } - } - return nullopt; + // Used to jump to file. + if (sym.kind == SymbolKind::File) + return Use(Range(Position(0, 0), Position(0, 0)), sym.id, sym.kind, + Role::None, QueryFileId(sym.id)); + Maybe ret; + EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.extent); }); + return ret; } Maybe GetDeclarationFileForSymbol(QueryDatabase* db, @@ -144,51 +101,6 @@ std::vector ToUses(QueryDatabase* db, const std::vector& ids) { return ToUsesHelper(db->vars, ids); } -std::vector GetUsesOfSymbol(QueryDatabase* db, - SymbolIdx sym, - bool include_decl) { - switch (sym.kind) { - case SymbolKind::Type: { - QueryType& type = db->GetType(sym); - std::vector ret = type.uses; - if (include_decl) { - for (auto& def : type.def) - if (def.spell) - ret.push_back(*def.spell); - AddRange(&ret, type.declarations); - } - return ret; - } - case SymbolKind::Func: { - QueryFunc& func = db->GetFunc(sym); - std::vector ret = func.uses; - if (include_decl) { - for (auto& def : func.def) - if (def.spell) - ret.push_back(*def.spell); - AddRange(&ret, func.declarations); - } - return ret; - } - case SymbolKind::Var: { - QueryVar& var = db->GetVar(sym); - std::vector ret = var.uses; - if (include_decl) { - for (auto& def : var.def) - if (def.spell) - ret.push_back(*def.spell); - ret.insert(ret.end(), var.declarations.begin(), var.declarations.end()); - } - return ret; - } - case SymbolKind::File: - case SymbolKind::Invalid: { - assert(false && "unexpected"); - return {}; - } - } -} - std::vector GetDeclarationsOfSymbolForGotoDefinition( QueryDatabase* db, SymbolIdx sym) { @@ -205,41 +117,30 @@ std::vector GetDeclarationsOfSymbolForGotoDefinition( } bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) { - // Check self. - if (!root.uses.empty()) - return true; - const QueryFunc::Def* def = root.AnyDef(); - - // Check for base calls. + std::unordered_set seen; std::queue queue; - EachWithGen(db->funcs, def->base, [&](QueryFunc& func) { - queue.push(&func); - }); + seen.insert(root.usr); + queue.push(&root); while (!queue.empty()) { QueryFunc& func = *queue.front(); queue.pop(); if (!func.uses.empty()) return true; - if (def) - EachWithGen(db->funcs, def->base, [&](QueryFunc& func1) { - queue.push(&func1); + if (auto* def = func.AnyDef()) { + EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) { + if (!seen.count(func1.usr)) { + seen.insert(func1.usr); + queue.push(&func1); + } }); + EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) { + if (!seen.count(func1.usr)) { + seen.insert(func1.usr); + queue.push(&func1); + } + }); + } } - - // Check for derived calls. - EachWithGen(db->funcs, root.derived, [&](QueryFunc& func1) { - queue.push(&func1); - }); - while (!queue.empty()) { - QueryFunc& func = *queue.front(); - queue.pop(); - if (!func.uses.empty()) - return true; - EachWithGen(db->funcs, func.derived, [&](QueryFunc& func1) { - queue.push(&func1); - }); - } - return false; } @@ -251,7 +152,7 @@ std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, return callers; std::queue queue; - EachWithGen(db->funcs, def->base, [&](QueryFunc& func1) { + EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) { queue.push(&func1); }); while (!queue.empty()) { @@ -260,7 +161,7 @@ std::vector GetCallersForAllBaseFunctions(QueryDatabase* db, AddRange(&callers, func.uses); if (const QueryFunc::Def* def1 = func.AnyDef()) { - EachWithGen(db->funcs, def1->base, [&](QueryFunc& func1) { + EachDefinedEntity(db->funcs, def1->base, [&](QueryFunc& func1) { queue.push(&func1); }); } @@ -274,7 +175,7 @@ std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, std::vector callers; std::queue queue; - EachWithGen(db->funcs, root.derived, [&](QueryFunc& func) { + EachDefinedEntity(db->funcs, root.derived, [&](QueryFunc& func) { queue.push(&func); }); @@ -282,7 +183,7 @@ std::vector GetCallersForAllDerivedFunctions(QueryDatabase* db, QueryFunc& func = *queue.front(); queue.pop(); - EachWithGen(db->funcs, func.derived, [&](QueryFunc& func1) { + EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) { queue.push(&func1); }); AddRange(&callers, func.uses); @@ -377,29 +278,12 @@ optional GetLsLocationEx(QueryDatabase* db, return nullopt; lsLocationEx ret; ret.lsLocation::operator=(*ls_loc); - if (extension) - switch (use.kind) { - default: - break; - case SymbolKind::Func: { - const QueryFunc::Def* def = db->GetFunc(use).AnyDef(); - if (def) - ret.containerName = std::string_view(def->detailed_name); - break; - } - case SymbolKind::Type: { - const QueryType::Def* def = db->GetType(use).AnyDef(); - if (def) - ret.containerName = std::string_view(def->detailed_name); - break; - } - case SymbolKind::Var: { - const QueryVar::Def* def = db->GetVar(use).AnyDef(); - if (def) - ret.containerName = std::string_view(def->detailed_name); - break; - } - } + if (extension) { + EachEntityDef(db, use, [&](const auto& def) { + ret.containerName = std::string_view(def.detailed_name); + return false; + }); + } return ret; } diff --git a/src/query_utils.h b/src/query_utils.h index 132093fe..4e6d5c24 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -18,9 +18,6 @@ std::vector ToUses(QueryDatabase* db, std::vector ToUses(QueryDatabase* db, const std::vector& ids); -std::vector GetUsesOfSymbol(QueryDatabase* db, - SymbolIdx sym, - bool include_decl); std::vector GetDeclarationsOfSymbolForGotoDefinition( QueryDatabase* db, SymbolIdx sym); @@ -64,43 +61,52 @@ void EmitDiagnostics(WorkingFiles* working_files, std::vector diagnostics); template -void EachDef(QueryDatabase* db, SymbolIdx sym, Fn fn) { +void WithEntity(QueryDatabase* db, SymbolIdx sym, Fn&& fn) { switch (sym.kind) { case SymbolKind::Invalid: case SymbolKind::File: break; case SymbolKind::Func: - for (auto& def : db->GetFunc(sym).def) - if (!fn(def)) - break; + fn(db->GetFunc(sym)); break; case SymbolKind::Type: - for (auto& def : db->GetType(sym).def) - if (!fn(def)) - break; + fn(db->GetType(sym)); break; case SymbolKind::Var: - for (auto& def : db->GetVar(sym).def) - if (!fn(def)) - break; + fn(db->GetVar(sym)); break; } } -template -void EachWithGen(std::vector& collection, Id x, Fn fn) { - Q& obj = collection[x.id]; - // FIXME Deprecate optional def - // if (obj.gen == x.gen && obj.def) - if (obj.AnyDef()) - fn(obj); +template +void EachEntityDef(QueryDatabase* db, SymbolIdx sym, Fn&& fn) { + WithEntity(db, sym, [&](const auto& entity) { + for (auto& def : entity.def) + if (!fn(def)) + break; + }); +} + +template +void EachUse(QueryDatabase* db, SymbolIdx sym, bool include_decl, Fn&& fn) { + WithEntity(db, sym, [&](const auto& entity) { + for (Use use : entity.uses) + fn(use); + if (include_decl) { + for (auto& def : entity.def) + if (def.spell) + fn(*def.spell); + for (Use use : entity.declarations) + fn(use); + } + }); } template -void EachWithGen(std::vector& collection, const std::vector>& ids, Fn fn) { +void EachDefinedEntity(std::vector& collection, const std::vector>& ids, Fn&& fn) { for (Id x : ids) { Q& obj = collection[x.id]; - if (obj.AnyDef()) + if (!obj.def.empty()) fn(obj); } }