From 8c328393622ea2b21d3fd7d0d60d5fc07ffc31bd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 25 Feb 2018 16:05:03 -0800 Subject: [PATCH] $cquery/{call,member}Hierarchy{Initial,Expand} work --- src/messages/cquery_call_hierarchy.cc | 136 ++++++++++++++---------- src/messages/cquery_member_hierarchy.cc | 8 +- 2 files changed, 83 insertions(+), 61 deletions(-) diff --git a/src/messages/cquery_call_hierarchy.cc b/src/messages/cquery_call_hierarchy.cc index cb53f8eb..5a515fd8 100644 --- a/src/messages/cquery_call_hierarchy.cc +++ b/src/messages/cquery_call_hierarchy.cc @@ -5,13 +5,25 @@ #include namespace { +enum class CallType : uint8_t { Direct = 0, Base = 1, Derived = 2, All = 1 | 2 }; +MAKE_REFLECT_TYPE_PROXY(CallType); + +bool operator&(CallType lhs, CallType rhs) { + return uint8_t(lhs) & uint8_t(rhs); +} + struct Ipc_CqueryCallHierarchyInitial : public RequestMessage { const static IpcId kIpcId = IpcId::CqueryCallHierarchyInitial; struct Params { lsTextDocumentIdentifier textDocument; lsPosition position; + // true: callee tree (functions called by this function); false: caller tree + // (where this function is called) bool callee = false; + // Base: include base functions; All: include both base and derived + // functions. + CallType callType = CallType::Direct; bool detailedName = false; int levels = 1; }; @@ -21,21 +33,19 @@ MAKE_REFLECT_STRUCT(Ipc_CqueryCallHierarchyInitial::Params, textDocument, position, callee, + callType, detailedName, levels); MAKE_REFLECT_STRUCT(Ipc_CqueryCallHierarchyInitial, id, params); REGISTER_IPC_MESSAGE(Ipc_CqueryCallHierarchyInitial); -enum class CallType { Direct = 0, Base = 1, Derived = 2, All = 1 | 2 }; -MAKE_REFLECT_TYPE_PROXY(CallType); - struct Ipc_CqueryCallHierarchyExpand : public RequestMessage { const static IpcId kIpcId = IpcId::CqueryCallHierarchyExpand; struct Params { Maybe id; - // true: callee tree; false: caller tree bool callee = false; + CallType callType = CallType::Direct; bool detailedName = false; int levels = 1; }; @@ -44,6 +54,7 @@ struct Ipc_CqueryCallHierarchyExpand MAKE_REFLECT_STRUCT(Ipc_CqueryCallHierarchyExpand::Params, id, callee, + callType, detailedName, levels); MAKE_REFLECT_STRUCT(Ipc_CqueryCallHierarchyExpand, id, params); @@ -75,6 +86,7 @@ MAKE_REFLECT_STRUCT(Out_CqueryCallHierarchy, jsonrpc, id, result); void Expand(MessageHandler* m, Out_CqueryCallHierarchy::Entry* entry, bool callee, + CallType call_type, bool detailed_name, int levels) { const QueryFunc& func = m->db->funcs[entry->id.id]; @@ -82,30 +94,25 @@ void Expand(MessageHandler* m, entry->numChildren = 0; if (!def) return; - if (def->spell) { - if (optional loc = - GetLsLocation(m->db, m->working_files, *def->spell)) - entry->location = *loc; - } auto handle = [&](Use use, CallType call_type) { - QueryFunc& rel_func = m->db->GetFunc(use); - const QueryFunc::Def* rel_def = rel_func.AnyDef(); - if (!rel_def) - return; - if (optional loc = - GetLsLocation(m->db, m->working_files, use)) { - entry->numChildren++; - if (levels > 0) { - Out_CqueryCallHierarchy::Entry entry1; - entry1.id = QueryFuncId(use.id); - if (detailed_name) - entry1.name = rel_def->detailed_name; - else - entry1.name = rel_def->ShortName(); - entry1.location = *loc; - entry1.callType = call_type; - Expand(m, &entry1, callee, detailed_name, levels - 1); - entry->children.push_back(std::move(entry1)); + entry->numChildren++; + if (levels > 0) { + QueryFunc& rel_func = m->db->GetFunc(use); + const QueryFunc::Def* rel_def = rel_func.AnyDef(); + if (!rel_def) + return; + if (optional loc = + GetLsLocation(m->db, m->working_files, use)) { + Out_CqueryCallHierarchy::Entry entry1; + entry1.id = QueryFuncId(use.id); + if (detailed_name) + entry1.name = rel_def->detailed_name; + else + entry1.name = rel_def->ShortName(); + entry1.location = *loc; + entry1.callType = call_type; + Expand(m, &entry1, callee, call_type, detailed_name, levels - 1); + entry->children.push_back(std::move(entry1)); } } }; @@ -127,33 +134,38 @@ void Expand(MessageHandler* m, handle_uses(func, CallType::Direct); // Callers/callees of base functions. - stack.push_back(&func); - while (stack.size()) { - const QueryFunc& func1 = *stack.back(); - stack.pop_back(); - if (auto* def1 = func1.AnyDef()) { - EachDefinedEntity(m->db->funcs, def1->base, [&](QueryFunc& func2) { - if (seen.count(func2.usr)) { - seen.insert(func2.usr); - stack.push_back(&func2); - handle_uses(func2, CallType::Base); - } - }); + if (call_type & CallType::Base) { + seen.insert(func.usr); + stack.push_back(&func); + while (stack.size()) { + const QueryFunc& func1 = *stack.back(); + stack.pop_back(); + if (auto* def1 = func1.AnyDef()) { + EachDefinedEntity(m->db->funcs, def1->base, [&](QueryFunc& func2) { + if (!seen.count(func2.usr)) { + seen.insert(func2.usr); + stack.push_back(&func2); + handle_uses(func2, CallType::Base); + } + }); + } } } // Callers/callees of derived functions. - stack.push_back(&func); - while (stack.size()) { - const QueryFunc& func1 = *stack.back(); - stack.pop_back(); - EachDefinedEntity(m->db->funcs, func1.derived, [&](QueryFunc& func2) { - if (seen.count(func2.usr)) { - seen.insert(func2.usr); - stack.push_back(&func2); - handle_uses(func2, CallType::Derived); - } - }); + if (call_type & CallType::Derived) { + stack.push_back(&func); + while (stack.size()) { + const QueryFunc& func1 = *stack.back(); + stack.pop_back(); + EachDefinedEntity(m->db->funcs, func1.derived, [&](QueryFunc& func2) { + if (!seen.count(func2.usr)) { + seen.insert(func2.usr); + stack.push_back(&func2); + handle_uses(func2, CallType::Derived); + } + }); + } } } @@ -161,6 +173,7 @@ struct CqueryCallHierarchyInitialHandler : BaseMessageHandler { optional BuildInitial(QueryFuncId root_id, bool callee, + CallType call_type, bool detailed_name, int levels) { const auto* def = db->funcs[root_id.id].AnyDef(); @@ -169,8 +182,16 @@ struct CqueryCallHierarchyInitialHandler Out_CqueryCallHierarchy::Entry entry; entry.id = root_id; - entry.name = def->ShortName(); - Expand(this, &entry, callee, detailed_name, levels); + if (detailed_name) + entry.name = def->detailed_name; + else + entry.name = def->ShortName(); + if (def->spell) { + if (optional loc = + GetLsLocation(db, working_files, *def->spell)) + entry.location = *loc; + } + Expand(this, &entry, callee, call_type, detailed_name, levels); return entry; } @@ -189,8 +210,9 @@ struct CqueryCallHierarchyInitialHandler for (SymbolRef sym : FindSymbolsAtLocation(working_file, file, params.position)) { if (sym.kind == SymbolKind::Func) { - out.result = BuildInitial(QueryFuncId(sym.id), params.callee, - params.detailedName, params.levels); + out.result = + BuildInitial(QueryFuncId(sym.id), params.callee, params.callType, + params.detailedName, params.levels); break; } } @@ -209,10 +231,10 @@ struct CqueryCallHierarchyExpandHandler if (params.id) { Out_CqueryCallHierarchy::Entry entry; entry.id = *params.id; - // entry.name is empty and it is known by the client. + // entry.name is empty as it is known by the client. if (entry.id.id < db->funcs.size()) - Expand(this, &entry, params.callee, params.detailedName, - params.levels); + Expand(this, &entry, params.callee, params.callType, + params.detailedName, params.levels); out.result = std::move(entry); } diff --git a/src/messages/cquery_member_hierarchy.cc b/src/messages/cquery_member_hierarchy.cc index 7508b705..b926b758 100644 --- a/src/messages/cquery_member_hierarchy.cc +++ b/src/messages/cquery_member_hierarchy.cc @@ -42,7 +42,7 @@ struct Out_CqueryMemberHierarchy struct Entry { QueryTypeId id; std::string_view name; - std::string_view field_name; + std::string_view fieldName; lsLocation location; // For unexpanded nodes, this is an upper bound because some entities may be // undefined. If it is 0, there are no members. @@ -56,7 +56,7 @@ struct Out_CqueryMemberHierarchy MAKE_REFLECT_STRUCT(Out_CqueryMemberHierarchy::Entry, id, name, - field_name, + fieldName, location, numChildren, children); @@ -115,7 +115,7 @@ void Expand(MessageHandler* m, const QueryVar::Def* def1 = var.AnyDef(); Out_CqueryMemberHierarchy::Entry entry1; entry1.id = def1->type ? *def1->type : QueryTypeId(); - entry1.field_name = def1->ShortName(); + entry1.fieldName = def1->ShortName(); Expand(m, &entry1, detailed_name, levels - 1); entry->children.push_back(std::move(entry1)); }); @@ -180,7 +180,7 @@ struct CqueryMemberHierarchyExpandHandler if (params.id) { Out_CqueryMemberHierarchy::Entry entry; entry.id = *request->params.id; - // entry.name is empty and it is known by the client. + // entry.name is empty as it is known by the client. if (entry.id.id < db->types.size()) Expand(this, &entry, params.detailedName, params.levels); out.result = std::move(entry);