Simplify query_utils

This commit is contained in:
Fangrui Song 2018-02-20 17:50:48 -08:00
parent 65ba98c3f8
commit 909c2e247a
10 changed files with 106 additions and 228 deletions

View File

@ -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<class T> 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();

View File

@ -61,7 +61,7 @@ ExpandNode(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) {
return {};
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();
Out_CqueryMemberHierarchy::Entry entry;
entry.name = def1->ShortName();

View File

@ -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)

View File

@ -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;

View File

@ -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<Use> 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.

View File

@ -39,28 +39,23 @@ struct TextDocumentDocumentHighlightHandler
for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references to highlight.
std::vector<Use> 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<lsLocation> 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<lsLocation> 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;
}

View File

@ -54,16 +54,13 @@ struct TextDocumentReferencesHandler
for (const SymbolRef& sym :
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references.
std::vector<Use> uses = GetUsesOfSymbol(
db, sym, request->params.context.includeDeclaration);
out.result.reserve(uses.size());
for (Use use : uses) {
optional<lsLocationEx> 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<lsLocationEx> ls_loc =
GetLsLocationEx(db, working_files, use,
config->extension.referenceContainer))
out.result.push_back(*ls_loc);
});
break;
}

View File

@ -6,15 +6,14 @@ namespace {
lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Use>& uses,
SymbolRef sym,
const std::string& new_text) {
std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit;
for (Use use : uses) {
optional<lsLocation> ls_location =
GetLsLocation(db, working_files, use);
EachUse(db, sym, true, [&](Use use) {
optional<lsLocation> 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<Ipc_TextDocumentRename> {
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;
}

View File

@ -6,6 +6,7 @@
#include <climits>
#include <queue>
#include <unordered_set>
namespace {
@ -40,63 +41,19 @@ std::vector<Use> ToUsesHelper(std::vector<Q>& entities,
Maybe<Use> 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<Use> ret;
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.spell); });
return ret;
}
Maybe<Use> 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<Use> ret;
EachEntityDef(db, sym, [&](const auto& def) { return !(ret = def.extent); });
return ret;
}
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);
}
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(
QueryDatabase* db,
SymbolIdx sym) {
@ -205,41 +117,30 @@ std::vector<Use> 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<Usr> seen;
std::queue<QueryFunc*> queue;
EachWithGen<QueryFunc>(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<QueryFunc>(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<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;
}
@ -251,7 +152,7 @@ std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
return callers;
std::queue<QueryFunc*> queue;
EachWithGen<QueryFunc>(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<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
AddRange(&callers, func.uses);
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);
});
}
@ -274,7 +175,7 @@ std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
std::vector<Use> callers;
std::queue<QueryFunc*> queue;
EachWithGen<QueryFunc>(db->funcs, root.derived, [&](QueryFunc& func) {
EachDefinedEntity(db->funcs, root.derived, [&](QueryFunc& func) {
queue.push(&func);
});
@ -282,7 +183,7 @@ std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
QueryFunc& func = *queue.front();
queue.pop();
EachWithGen<QueryFunc>(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<lsLocationEx> 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;
}

View File

@ -18,9 +18,6 @@ std::vector<Use> ToUses(QueryDatabase* db,
std::vector<Use> ToUses(QueryDatabase* db,
const std::vector<QueryVarId>& ids);
std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
SymbolIdx sym,
bool include_decl);
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
QueryDatabase* db,
SymbolIdx sym);
@ -64,43 +61,52 @@ void EmitDiagnostics(WorkingFiles* working_files,
std::vector<lsDiagnostic> diagnostics);
template <typename Fn>
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 <typename Q, typename Fn>
void EachWithGen(std::vector<Q>& collection, Id<Q> x, 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 Fn>
void EachEntityDef(QueryDatabase* db, SymbolIdx sym, Fn&& fn) {
WithEntity(db, sym, [&](const auto& entity) {
for (auto& def : entity.def)
if (!fn(def))
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>
void EachWithGen(std::vector<Q>& collection, const std::vector<Id<Q>>& ids, Fn fn) {
void EachDefinedEntity(std::vector<Q>& collection, const std::vector<Id<Q>>& ids, Fn&& fn) {
for (Id<Q> x : ids) {
Q& obj = collection[x.id];
if (obj.AnyDef())
if (!obj.def.empty())
fn(obj);
}
}