in source/CallGraph.cpp [700:764]
Json::Value CallGraph::to_json(bool with_overrides) const {
auto value = Json::Value(Json::objectValue);
for (const auto& [method, callees] : resolved_base_callees_) {
auto method_value = Json::Value(Json::objectValue);
std::unordered_set<const Method*> static_callees;
std::unordered_set<const Method*> virtual_callees;
for (const auto& [instruction, resolved_base_callee] : callees) {
auto call_target = CallTarget::from_call_instruction(
method,
instruction,
resolved_base_callee,
types_,
class_hierarchies_,
overrides_);
if (!call_target.resolved()) {
continue;
} else if (call_target.is_virtual()) {
virtual_callees.insert(call_target.resolved_base_callee());
if (with_overrides) {
for (const auto* override : call_target.overrides()) {
virtual_callees.insert(override);
}
}
} else {
static_callees.insert(call_target.resolved_base_callee());
}
}
if (!static_callees.empty()) {
auto static_callees_value = Json::Value(Json::arrayValue);
for (const auto* callee : static_callees) {
static_callees_value.append(Json::Value(show(callee)));
}
method_value["static"] = static_callees_value;
}
if (!virtual_callees.empty()) {
auto virtual_callees_value = Json::Value(Json::arrayValue);
for (const auto* callee : virtual_callees) {
virtual_callees_value.append(Json::Value(show(callee)));
}
method_value["virtual"] = virtual_callees_value;
}
value[show(method)] = method_value;
}
for (const auto& [method, instruction_artificial_callees] :
artificial_callees_) {
std::unordered_set<const Method*> callees;
for (const auto& [instruction, artificial_callees] :
instruction_artificial_callees) {
for (const auto& artificial_callee : artificial_callees) {
callees.insert(artificial_callee.call_target.resolved_base_callee());
}
}
auto callees_value = Json::Value(Json::arrayValue);
for (const auto* callee : callees) {
callees_value.append(Json::Value(show(callee)));
}
value[show(method)]["artificial"] = callees_value;
}
return value;
}