From 74ef7dd790758ea221e7d0c7400771602665d0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 28 Jan 2021 19:20:00 +0100 Subject: [PATCH] FunctionCallGraph: operator<< for printing nodes in an unambiguous way --- libsolidity/analysis/FunctionCallGraph.cpp | 63 ++++++++++++++++++++++ libsolidity/analysis/FunctionCallGraph.h | 3 ++ 2 files changed, 66 insertions(+) diff --git a/libsolidity/analysis/FunctionCallGraph.cpp b/libsolidity/analysis/FunctionCallGraph.cpp index 7808e4134..aa182cd3a 100644 --- a/libsolidity/analysis/FunctionCallGraph.cpp +++ b/libsolidity/analysis/FunctionCallGraph.cpp @@ -18,12 +18,16 @@ #include +#include + +#include #include #include using namespace std; using namespace ranges; using namespace solidity::frontend; +using namespace solidity::util; bool FunctionCallGraphBuilder::CompareByID::operator()(Node const& _lhs, Node const& _rhs) const { @@ -278,3 +282,62 @@ void FunctionCallGraphBuilder::functionReferenced(CallableDeclaration const& _ca enqueueCallable(_callable); } + +ostream& solidity::frontend::operator<<(ostream& _out, FunctionCallGraphBuilder::Node const& _node) +{ + using SpecialNode = FunctionCallGraphBuilder::SpecialNode; + + if (holds_alternative(_node)) + switch (get(_node)) + { + case SpecialNode::InternalDispatch: + _out << "InternalDispatch"; + break; + case SpecialNode::Entry: + _out << "Entry"; + break; + default: solAssert(false, "Invalid SpecialNode type"); + } + else + { + solAssert(holds_alternative(_node), ""); + + auto const* callableDeclaration = get(_node); + solAssert(callableDeclaration, ""); + + auto const* function = dynamic_cast(callableDeclaration); + auto const* event = dynamic_cast(callableDeclaration); + auto const* modifier = dynamic_cast(callableDeclaration); + + auto typeToString = [](auto const& _var) -> string { return _var->type()->toString(true); }; + vector parameters = callableDeclaration->parameters() | views::transform(typeToString) | to>(); + + string scopeName; + if (!function || !function->isFree()) + { + solAssert(callableDeclaration->annotation().scope, ""); + auto const* parentContract = dynamic_cast(callableDeclaration->annotation().scope); + solAssert(parentContract, ""); + scopeName = parentContract->name(); + } + + if (function && function->isFree()) + _out << "function " << function->name() << "(" << joinHumanReadable(parameters, ",") << ")"; + else if (function && function->isConstructor()) + _out << "constructor of " << scopeName; + else if (function && function->isFallback()) + _out << "fallback of " << scopeName; + else if (function && function->isReceive()) + _out << "receive of " << scopeName; + else if (function) + _out << "function " << scopeName << "." << function->name() << "(" << joinHumanReadable(parameters, ",") << ")"; + else if (event) + _out << "event " << scopeName << "." << event->name() << "(" << joinHumanReadable(parameters, ",") << ")"; + else if (modifier) + _out << "modifier " << scopeName << "." << modifier->name(); + else + solAssert(false, "Unexpected AST node type in function call graph"); + } + + return _out; +} diff --git a/libsolidity/analysis/FunctionCallGraph.h b/libsolidity/analysis/FunctionCallGraph.h index 59f239b0e..53d1dceb2 100644 --- a/libsolidity/analysis/FunctionCallGraph.h +++ b/libsolidity/analysis/FunctionCallGraph.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -119,4 +120,6 @@ private: std::deque m_visitQueue; }; +std::ostream& operator<<(std::ostream& _out, FunctionCallGraphBuilder::Node const& _node); + }