FunctionCallGraph: operator<< for printing nodes in an unambiguous way

This commit is contained in:
Kamil Śliwak 2021-01-28 19:20:00 +01:00
parent 4c1f8d69f9
commit 74ef7dd790
2 changed files with 66 additions and 0 deletions

View File

@ -18,12 +18,16 @@
#include <libsolidity/analysis/FunctionCallGraph.h>
#include <libsolutil/StringUtils.h>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/reverse.hpp>
#include <range/v3/view/transform.hpp>
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<SpecialNode>(_node))
switch (get<SpecialNode>(_node))
{
case SpecialNode::InternalDispatch:
_out << "InternalDispatch";
break;
case SpecialNode::Entry:
_out << "Entry";
break;
default: solAssert(false, "Invalid SpecialNode type");
}
else
{
solAssert(holds_alternative<CallableDeclaration const*>(_node), "");
auto const* callableDeclaration = get<CallableDeclaration const*>(_node);
solAssert(callableDeclaration, "");
auto const* function = dynamic_cast<FunctionDefinition const *>(callableDeclaration);
auto const* event = dynamic_cast<EventDefinition const *>(callableDeclaration);
auto const* modifier = dynamic_cast<ModifierDefinition const *>(callableDeclaration);
auto typeToString = [](auto const& _var) -> string { return _var->type()->toString(true); };
vector<string> parameters = callableDeclaration->parameters() | views::transform(typeToString) | to<vector<string>>();
string scopeName;
if (!function || !function->isFree())
{
solAssert(callableDeclaration->annotation().scope, "");
auto const* parentContract = dynamic_cast<ContractDefinition const*>(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;
}

View File

@ -22,6 +22,7 @@
#include <libsolidity/ast/ASTVisitor.h>
#include <deque>
#include <ostream>
#include <variant>
#include <vector>
@ -119,4 +120,6 @@ private:
std::deque<CallableDeclaration const*> m_visitQueue;
};
std::ostream& operator<<(std::ostream& _out, FunctionCallGraphBuilder::Node const& _node);
}