mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Extend using-for.
This commit is contained in:
+49
-22
@@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user