mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 23:55:08 +00:00
Simplify query_utils
This commit is contained in:
parent
65ba98c3f8
commit
909c2e247a
@ -685,7 +685,6 @@ const int IndexFile::kMinorVersion = 0;
|
|||||||
IndexFile::IndexFile(const std::string& path, const std::string& contents)
|
IndexFile::IndexFile(const std::string& path, const std::string& contents)
|
||||||
: id_cache(path), path(path), file_contents(contents) {}
|
: id_cache(path), path(path), file_contents(contents) {}
|
||||||
|
|
||||||
// TODO: Optimize for const char*?
|
|
||||||
IndexTypeId IndexFile::ToTypeId(Usr usr) {
|
IndexTypeId IndexFile::ToTypeId(Usr usr) {
|
||||||
auto it = id_cache.usr_to_type_id.find(usr);
|
auto it = id_cache.usr_to_type_id.find(usr);
|
||||||
if (it != id_cache.usr_to_type_id.end())
|
if (it != id_cache.usr_to_type_id.end())
|
||||||
@ -1358,7 +1357,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
sem_parent, Role::Definition);
|
sem_parent, Role::Definition);
|
||||||
ref_type->def.extent =
|
ref_type->def.extent =
|
||||||
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
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);
|
ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor);
|
||||||
#else
|
#else
|
||||||
ref_type->def.detailed_name = ref_cursor.get_spell_name();
|
ref_type->def.detailed_name = ref_cursor.get_spell_name();
|
||||||
@ -1392,7 +1391,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
sem_parent, Role::Definition);
|
sem_parent, Role::Definition);
|
||||||
ref_type->def.extent =
|
ref_type->def.extent =
|
||||||
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
SetUse(db, ref_cursor.get_extent(), lex_parent, Role::None);
|
||||||
#if CINDEX_HAVE_PRETTY
|
#if 0&&CINDEX_HAVE_PRETTY
|
||||||
|
// template<class T> void f(T t){} // weird, the name is empty
|
||||||
ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor);
|
ref_type->def.detailed_name = param->PrettyPrintCursor(ref_cursor.cx_cursor);
|
||||||
#else
|
#else
|
||||||
ref_type->def.detailed_name = ref_cursor.get_spell_name();
|
ref_type->def.detailed_name = ref_cursor.get_spell_name();
|
||||||
|
@ -61,7 +61,7 @@ ExpandNode(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) {
|
|||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::vector<Out_CqueryMemberHierarchy::Entry> ret;
|
std::vector<Out_CqueryMemberHierarchy::Entry> ret;
|
||||||
EachWithGen(db->vars, def->vars, [&](QueryVar& var) {
|
EachDefinedEntity(db->vars, def->vars, [&](QueryVar& var) {
|
||||||
const QueryVar::Def* def1 = var.AnyDef();
|
const QueryVar::Def* def1 = var.AnyDef();
|
||||||
Out_CqueryMemberHierarchy::Entry entry;
|
Out_CqueryMemberHierarchy::Entry entry;
|
||||||
entry.name = def1->ShortName();
|
entry.name = def1->ShortName();
|
||||||
|
@ -35,7 +35,7 @@ BuildParentInheritanceHierarchyForType(QueryDatabase* db,
|
|||||||
const QueryType::Def* def = root_type.AnyDef();
|
const QueryType::Def* def = root_type.AnyDef();
|
||||||
parent_entries.reserve(def->parents.size());
|
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;
|
Out_CqueryTypeHierarchyTree::TypeEntry parent_entry;
|
||||||
const QueryType::Def* def1 = parent_type.AnyDef();
|
const QueryType::Def* def1 = parent_type.AnyDef();
|
||||||
parent_entry.name = def1->detailed_name.c_str();
|
parent_entry.name = def1->detailed_name.c_str();
|
||||||
@ -74,7 +74,7 @@ BuildInheritanceHierarchyForType(QueryDatabase* db,
|
|||||||
entry.children.push_back(base);
|
entry.children.push_back(base);
|
||||||
|
|
||||||
// Add derived.
|
// Add derived.
|
||||||
EachWithGen(db->types, root_type.derived, [&](QueryType& type) {
|
EachDefinedEntity(db->types, root_type.derived, [&](QueryType& type) {
|
||||||
auto derived_entry =
|
auto derived_entry =
|
||||||
BuildInheritanceHierarchyForType(db, working_files, type);
|
BuildInheritanceHierarchyForType(db, working_files, type);
|
||||||
if (derived_entry)
|
if (derived_entry)
|
||||||
|
@ -359,7 +359,7 @@ struct TextDocumentCodeActionHandler
|
|||||||
// Get implementation file.
|
// Get implementation file.
|
||||||
Out_TextDocumentCodeAction::Command command;
|
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();
|
const QueryFunc::Def* def1 = func_def.AnyDef();
|
||||||
if (def1->extent)
|
if (def1->extent)
|
||||||
return;
|
return;
|
||||||
|
@ -81,7 +81,7 @@ struct TextDocumentDefinitionHandler
|
|||||||
// - start at spelling but end at extent for better mouse tooltip
|
// - start at spelling but end at extent for better mouse tooltip
|
||||||
// - goto declaration while in definition of recursive type
|
// - goto declaration while in definition of recursive type
|
||||||
std::vector<Use> uses;
|
std::vector<Use> uses;
|
||||||
EachDef(db, sym, [&](const auto& def) {
|
EachEntityDef(db, sym, [&](const auto& def) {
|
||||||
if (def.spell && def.extent) {
|
if (def.spell && def.extent) {
|
||||||
Use spell = *def.spell;
|
Use spell = *def.spell;
|
||||||
// If on a definition, clear |uses| to find declarations below.
|
// If on a definition, clear |uses| to find declarations below.
|
||||||
|
@ -39,19 +39,13 @@ struct TextDocumentDocumentHighlightHandler
|
|||||||
for (SymbolRef sym :
|
for (SymbolRef sym :
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
// Found symbol. Return references to highlight.
|
// Found symbol. Return references to highlight.
|
||||||
std::vector<Use> uses = GetUsesOfSymbol(db, sym, true);
|
EachUse(db, sym, true, [&](Use use) {
|
||||||
out.result.reserve(uses.size());
|
|
||||||
for (Use use : uses) {
|
|
||||||
if (use.file != file_id)
|
if (use.file != file_id)
|
||||||
continue;
|
return;
|
||||||
|
if (optional<lsLocation> ls_loc =
|
||||||
optional<lsLocation> ls_location =
|
GetLsLocation(db, working_files, use)) {
|
||||||
GetLsLocation(db, working_files, use);
|
|
||||||
if (!ls_location)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
lsDocumentHighlight highlight;
|
lsDocumentHighlight highlight;
|
||||||
highlight.range = ls_location->range;
|
highlight.range = ls_loc->range;
|
||||||
if (use.role & Role::Write)
|
if (use.role & Role::Write)
|
||||||
highlight.kind = lsDocumentHighlightKind::Write;
|
highlight.kind = lsDocumentHighlightKind::Write;
|
||||||
else if (use.role & Role::Read)
|
else if (use.role & Role::Read)
|
||||||
@ -61,6 +55,7 @@ struct TextDocumentDocumentHighlightHandler
|
|||||||
highlight.role = use.role;
|
highlight.role = use.role;
|
||||||
out.result.push_back(highlight);
|
out.result.push_back(highlight);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,16 +54,13 @@ struct TextDocumentReferencesHandler
|
|||||||
for (const SymbolRef& sym :
|
for (const SymbolRef& sym :
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
// Found symbol. Return references.
|
// Found symbol. Return references.
|
||||||
std::vector<Use> uses = GetUsesOfSymbol(
|
EachUse(db, sym, request->params.context.includeDeclaration,
|
||||||
db, sym, request->params.context.includeDeclaration);
|
[&](Use use) {
|
||||||
out.result.reserve(uses.size());
|
if (optional<lsLocationEx> ls_loc =
|
||||||
for (Use use : uses) {
|
GetLsLocationEx(db, working_files, use,
|
||||||
optional<lsLocationEx> ls_loc = GetLsLocationEx(
|
config->extension.referenceContainer))
|
||||||
db, working_files, use, config->extension.referenceContainer);
|
|
||||||
if (ls_loc) {
|
|
||||||
out.result.push_back(*ls_loc);
|
out.result.push_back(*ls_loc);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,15 +6,14 @@ namespace {
|
|||||||
|
|
||||||
lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
|
lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
const std::vector<Use>& uses,
|
SymbolRef sym,
|
||||||
const std::string& new_text) {
|
const std::string& new_text) {
|
||||||
std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit;
|
std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit;
|
||||||
|
|
||||||
for (Use use : uses) {
|
EachUse(db, sym, true, [&](Use use) {
|
||||||
optional<lsLocation> ls_location =
|
optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
|
||||||
GetLsLocation(db, working_files, use);
|
|
||||||
if (!ls_location)
|
if (!ls_location)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
QueryFileId file_id = use.file;
|
QueryFileId file_id = use.file;
|
||||||
if (path_to_edit.find(file_id) == path_to_edit.end()) {
|
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];
|
QueryFile& file = db->files[file_id.id];
|
||||||
if (!file.def)
|
if (!file.def)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
const std::string& path = file.def->path;
|
const std::string& path = file.def->path;
|
||||||
path_to_edit[file_id].textDocument.uri =
|
path_to_edit[file_id].textDocument.uri = lsDocumentUri::FromPath(path);
|
||||||
lsDocumentUri::FromPath(path);
|
|
||||||
|
|
||||||
WorkingFile* working_file = working_files->GetFileByFilename(path);
|
WorkingFile* working_file = working_files->GetFileByFilename(path);
|
||||||
if (working_file)
|
if (working_file)
|
||||||
path_to_edit[file_id].textDocument.version =
|
path_to_edit[file_id].textDocument.version = working_file->version;
|
||||||
working_file->version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lsTextEdit edit;
|
lsTextEdit edit;
|
||||||
@ -42,7 +39,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
|
|||||||
auto& edits = path_to_edit[file_id].edits;
|
auto& edits = path_to_edit[file_id].edits;
|
||||||
if (std::find(edits.begin(), edits.end(), edit) == edits.end())
|
if (std::find(edits.begin(), edits.end(), edit) == edits.end())
|
||||||
edits.push_back(edit);
|
edits.push_back(edit);
|
||||||
}
|
});
|
||||||
|
|
||||||
lsWorkspaceEdit edit;
|
lsWorkspaceEdit edit;
|
||||||
for (const auto& changes : path_to_edit)
|
for (const auto& changes : path_to_edit)
|
||||||
@ -98,9 +95,8 @@ struct TextDocumentRenameHandler : BaseMessageHandler<Ipc_TextDocumentRename> {
|
|||||||
for (SymbolRef sym :
|
for (SymbolRef sym :
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
// Found symbol. Return references to rename.
|
// Found symbol. Return references to rename.
|
||||||
out.result = BuildWorkspaceEdit(db, working_files,
|
out.result =
|
||||||
GetUsesOfSymbol(db, sym, true),
|
BuildWorkspaceEdit(db, working_files, sym, request->params.newName);
|
||||||
request->params.newName);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -40,63 +41,19 @@ std::vector<Use> ToUsesHelper(std::vector<Q>& entities,
|
|||||||
|
|
||||||
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
|
Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
|
||||||
SymbolIdx sym) {
|
SymbolIdx sym) {
|
||||||
switch (sym.kind) {
|
Maybe<Use> ret;
|
||||||
case SymbolKind::File:
|
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.spell); });
|
||||||
break;
|
return ret;
|
||||||
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<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym) {
|
Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym) {
|
||||||
switch (sym.kind) {
|
// Used to jump to file.
|
||||||
case SymbolKind::File:
|
if (sym.kind == SymbolKind::File)
|
||||||
return Use(Range(Position(0, 0), Position(0, 0)), sym.id, sym.kind,
|
return Use(Range(Position(0, 0), Position(0, 0)), sym.id, sym.kind,
|
||||||
Role::None, QueryFileId(sym.id));
|
Role::None, QueryFileId(sym.id));
|
||||||
case SymbolKind::Func: {
|
Maybe<Use> ret;
|
||||||
for (auto& def : db->GetFunc(sym).def)
|
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.extent); });
|
||||||
if (def.extent)
|
return ret;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
||||||
@ -144,51 +101,6 @@ std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
|
|||||||
return ToUsesHelper(db->vars, ids);
|
return ToUsesHelper(db->vars, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
|
|
||||||
SymbolIdx sym,
|
|
||||||
bool include_decl) {
|
|
||||||
switch (sym.kind) {
|
|
||||||
case SymbolKind::Type: {
|
|
||||||
QueryType& type = db->GetType(sym);
|
|
||||||
std::vector<Use> 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<Use> 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<Use> 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<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
||||||
QueryDatabase* db,
|
QueryDatabase* db,
|
||||||
SymbolIdx sym) {
|
SymbolIdx sym) {
|
||||||
@ -205,41 +117,30 @@ std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
|
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
|
||||||
// Check self.
|
std::unordered_set<Usr> seen;
|
||||||
if (!root.uses.empty())
|
|
||||||
return true;
|
|
||||||
const QueryFunc::Def* def = root.AnyDef();
|
|
||||||
|
|
||||||
// Check for base calls.
|
|
||||||
std::queue<QueryFunc*> queue;
|
std::queue<QueryFunc*> queue;
|
||||||
EachWithGen<QueryFunc>(db->funcs, def->base, [&](QueryFunc& func) {
|
seen.insert(root.usr);
|
||||||
queue.push(&func);
|
queue.push(&root);
|
||||||
});
|
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
QueryFunc& func = *queue.front();
|
QueryFunc& func = *queue.front();
|
||||||
queue.pop();
|
queue.pop();
|
||||||
if (!func.uses.empty())
|
if (!func.uses.empty())
|
||||||
return true;
|
return true;
|
||||||
if (def)
|
if (auto* def = func.AnyDef()) {
|
||||||
EachWithGen<QueryFunc>(db->funcs, def->base, [&](QueryFunc& func1) {
|
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
|
||||||
|
if (!seen.count(func1.usr)) {
|
||||||
|
seen.insert(func1.usr);
|
||||||
queue.push(&func1);
|
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<QueryFunc>(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<QueryFunc>(db->funcs, func.derived, [&](QueryFunc& func1) {
|
|
||||||
queue.push(&func1);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +152,7 @@ std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
|||||||
return callers;
|
return callers;
|
||||||
|
|
||||||
std::queue<QueryFunc*> queue;
|
std::queue<QueryFunc*> queue;
|
||||||
EachWithGen<QueryFunc>(db->funcs, def->base, [&](QueryFunc& func1) {
|
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
|
||||||
queue.push(&func1);
|
queue.push(&func1);
|
||||||
});
|
});
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
@ -260,7 +161,7 @@ std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
|||||||
|
|
||||||
AddRange(&callers, func.uses);
|
AddRange(&callers, func.uses);
|
||||||
if (const QueryFunc::Def* def1 = func.AnyDef()) {
|
if (const QueryFunc::Def* def1 = func.AnyDef()) {
|
||||||
EachWithGen<QueryFunc>(db->funcs, def1->base, [&](QueryFunc& func1) {
|
EachDefinedEntity(db->funcs, def1->base, [&](QueryFunc& func1) {
|
||||||
queue.push(&func1);
|
queue.push(&func1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -274,7 +175,7 @@ std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
|
|||||||
std::vector<Use> callers;
|
std::vector<Use> callers;
|
||||||
|
|
||||||
std::queue<QueryFunc*> queue;
|
std::queue<QueryFunc*> queue;
|
||||||
EachWithGen<QueryFunc>(db->funcs, root.derived, [&](QueryFunc& func) {
|
EachDefinedEntity(db->funcs, root.derived, [&](QueryFunc& func) {
|
||||||
queue.push(&func);
|
queue.push(&func);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -282,7 +183,7 @@ std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
|
|||||||
QueryFunc& func = *queue.front();
|
QueryFunc& func = *queue.front();
|
||||||
queue.pop();
|
queue.pop();
|
||||||
|
|
||||||
EachWithGen<QueryFunc>(db->funcs, func.derived, [&](QueryFunc& func1) {
|
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
|
||||||
queue.push(&func1);
|
queue.push(&func1);
|
||||||
});
|
});
|
||||||
AddRange(&callers, func.uses);
|
AddRange(&callers, func.uses);
|
||||||
@ -377,28 +278,11 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
|||||||
return nullopt;
|
return nullopt;
|
||||||
lsLocationEx ret;
|
lsLocationEx ret;
|
||||||
ret.lsLocation::operator=(*ls_loc);
|
ret.lsLocation::operator=(*ls_loc);
|
||||||
if (extension)
|
if (extension) {
|
||||||
switch (use.kind) {
|
EachEntityDef(db, use, [&](const auto& def) {
|
||||||
default:
|
ret.containerName = std::string_view(def.detailed_name);
|
||||||
break;
|
return false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,6 @@ std::vector<Use> ToUses(QueryDatabase* db,
|
|||||||
std::vector<Use> ToUses(QueryDatabase* db,
|
std::vector<Use> ToUses(QueryDatabase* db,
|
||||||
const std::vector<QueryVarId>& ids);
|
const std::vector<QueryVarId>& ids);
|
||||||
|
|
||||||
std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
|
|
||||||
SymbolIdx sym,
|
|
||||||
bool include_decl);
|
|
||||||
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
||||||
QueryDatabase* db,
|
QueryDatabase* db,
|
||||||
SymbolIdx sym);
|
SymbolIdx sym);
|
||||||
@ -64,43 +61,52 @@ void EmitDiagnostics(WorkingFiles* working_files,
|
|||||||
std::vector<lsDiagnostic> diagnostics);
|
std::vector<lsDiagnostic> diagnostics);
|
||||||
|
|
||||||
template <typename Fn>
|
template <typename Fn>
|
||||||
void EachDef(QueryDatabase* db, SymbolIdx sym, Fn fn) {
|
void WithEntity(QueryDatabase* db, SymbolIdx sym, Fn&& fn) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Invalid:
|
case SymbolKind::Invalid:
|
||||||
case SymbolKind::File:
|
case SymbolKind::File:
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Func:
|
case SymbolKind::Func:
|
||||||
for (auto& def : db->GetFunc(sym).def)
|
fn(db->GetFunc(sym));
|
||||||
if (!fn(def))
|
|
||||||
break;
|
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Type:
|
case SymbolKind::Type:
|
||||||
for (auto& def : db->GetType(sym).def)
|
fn(db->GetType(sym));
|
||||||
if (!fn(def))
|
|
||||||
break;
|
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var:
|
case SymbolKind::Var:
|
||||||
for (auto& def : db->GetVar(sym).def)
|
fn(db->GetVar(sym));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fn>
|
||||||
|
void EachEntityDef(QueryDatabase* db, SymbolIdx sym, Fn&& fn) {
|
||||||
|
WithEntity(db, sym, [&](const auto& entity) {
|
||||||
|
for (auto& def : entity.def)
|
||||||
if (!fn(def))
|
if (!fn(def))
|
||||||
break;
|
break;
|
||||||
break;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Fn>
|
||||||
|
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 <typename Q, typename Fn>
|
template <typename Q, typename Fn>
|
||||||
void EachWithGen(std::vector<Q>& collection, Id<Q> x, Fn fn) {
|
void EachDefinedEntity(std::vector<Q>& collection, const std::vector<Id<Q>>& ids, Fn&& fn) {
|
||||||
Q& obj = collection[x.id];
|
|
||||||
// FIXME Deprecate optional<Def> def
|
|
||||||
// if (obj.gen == x.gen && obj.def)
|
|
||||||
if (obj.AnyDef())
|
|
||||||
fn(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Q, typename Fn>
|
|
||||||
void EachWithGen(std::vector<Q>& collection, const std::vector<Id<Q>>& ids, Fn fn) {
|
|
||||||
for (Id<Q> x : ids) {
|
for (Id<Q> x : ids) {
|
||||||
Q& obj = collection[x.id];
|
Q& obj = collection[x.id];
|
||||||
if (obj.AnyDef())
|
if (!obj.def.empty())
|
||||||
fn(obj);
|
fn(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user