Extend using-for.

This commit is contained in:
hrkrshnn
2022-03-14 12:33:44 +01:00
committed by chriseth
parent db30f4d495
commit 672951ccc7
55 changed files with 992 additions and 150 deletions
+49 -22
View File
@@ -35,6 +35,7 @@
#include <libsolutil/Keccak256.h>
#include <libsolutil/StringUtils.h>
#include <libsolutil/UTF8.h>
#include <libsolutil/Visitor.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
@@ -331,30 +332,48 @@ Type const* Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c
MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)
{
vector<UsingForDirective const*> usingForDirectives;
if (auto const* sourceUnit = dynamic_cast<SourceUnit const*>(&_scope))
usingForDirectives += ASTNode::filteredNodes<UsingForDirective>(sourceUnit->nodes());
else if (auto const* contract = dynamic_cast<ContractDefinition const*>(&_scope))
usingForDirectives +=
contract->usingForDirectives() +
ASTNode::filteredNodes<UsingForDirective>(contract->sourceUnit().nodes());
SourceUnit const* sourceUnit = dynamic_cast<SourceUnit const*>(&_scope);
if (auto const* contract = dynamic_cast<ContractDefinition const*>(&_scope))
{
sourceUnit = &contract->sourceUnit();
usingForDirectives += contract->usingForDirectives();
}
else
solAssert(false, "");
solAssert(sourceUnit, "");
usingForDirectives += ASTNode::filteredNodes<UsingForDirective>(sourceUnit->nodes());
// Normalise data location of type.
DataLocation typeLocation = DataLocation::Storage;
if (auto refType = dynamic_cast<ReferenceType const*>(&_type))
typeLocation = refType->location();
set<Declaration const*> seenFunctions;
MemberList::MemberMap members;
set<pair<string, Declaration const*>> seenFunctions;
auto addFunction = [&](FunctionDefinition const& _function, optional<string> _name = {})
{
if (!_name)
_name = _function.name();
Type const* functionType =
_function.libraryFunction() ? _function.typeViaContractName() : _function.type();
solAssert(functionType, "");
FunctionType const* asBoundFunction =
dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
solAssert(asBoundFunction, "");
if (_type.isImplicitlyConvertibleTo(*asBoundFunction->selfType()))
if (seenFunctions.insert(make_pair(*_name, &_function)).second)
members.emplace_back(&_function, asBoundFunction, *_name);
};
for (UsingForDirective const* ufd: usingForDirectives)
{
// Convert both types to pointers for comparison to see if the `using for`
// directive applies.
// Further down, we check more detailed for each function if `_type` is
// convertible to the function parameter type.
if (ufd->typeName() &&
if (
ufd->typeName() &&
*TypeProvider::withLocationIfReference(typeLocation, &_type, true) !=
*TypeProvider::withLocationIfReference(
typeLocation,
@@ -363,20 +382,28 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
)
)
continue;
auto const& library = dynamic_cast<ContractDefinition const&>(
*ufd->libraryName().annotation().referencedDeclaration
);
for (FunctionDefinition const* function: library.definedFunctions())
for (auto const& pathPointer: ufd->functionsOrLibrary())
{
if (!function->isOrdinary() || !function->isVisibleAsLibraryMember() || seenFunctions.count(function))
continue;
seenFunctions.insert(function);
if (function->parameters().empty())
continue;
FunctionTypePointer fun =
dynamic_cast<FunctionType const&>(*function->typeViaContractName()).asBoundFunction();
if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
members.emplace_back(function, fun);
solAssert(pathPointer);
Declaration const* declaration = pathPointer->annotation().referencedDeclaration;
solAssert(declaration);
if (ContractDefinition const* library = dynamic_cast<ContractDefinition const*>(declaration))
{
solAssert(library->isLibrary());
for (FunctionDefinition const* function: library->definedFunctions())
{
if (!function->isOrdinary() || !function->isVisibleAsLibraryMember() || function->parameters().empty())
continue;
addFunction(*function);
}
}
else
addFunction(
dynamic_cast<FunctionDefinition const&>(*declaration),
pathPointer->path().back()
);
}
}