From 6d9020b3b80aff0baf7d6e023460cfbcd930de6b Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Thu, 5 Jan 2017 12:01:27 -0600 Subject: [PATCH] fixed test and added solution Signed-off-by: VoR0220 --- libsolidity/interface/CompilerStack.cpp | 29 ++++++++++++++++++++++--- test/libsolidity/Imports.cpp | 4 ++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index ee55f41af..a097e4c8b 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -507,21 +507,44 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context return false; return std::equal(_a.begin(), _a.end(), _b.begin()); }; + // Try to find whether _a is a closer match for context _reference than _b + // Defaults to longest prefix in case of a tie. + auto isClosestContext = [](string const& _a, string const& _b, string const& _reference) + { + int a = _reference.compare(_a); + int b = _reference.compare(_b); + if (a == 0) + return true; + else if (b == 0) + return false; + else if (abs(a) == abs(b)) { + return a > 0; + } + return abs(a) < abs(b); + }; + using filepath = boost::filesystem::path; + filepath context(_context); size_t longestPrefix = 0; string longestPrefixTarget; + string currentClosestContext; + string referenceContext = context.parent_path().generic_string(); for (auto const& redir: m_remappings) { + filepath redirContext(redir.context); // Skip if we already have a closer match. - if (longestPrefix > 0 && redir.prefix.length() <= longestPrefix) + if (longestPrefix > 0 && redir.prefix.length() < longestPrefix) continue; // Skip if redir.context is not a prefix of _context - if (!isPrefixOf(redir.context, _context)) + if (!isPrefixOf(redirContext.generic_string(), _context)) continue; // Skip if the prefix does not match. if (!isPrefixOf(redir.prefix, _path)) continue; - + // Skip if there is a prefix collision and the current context is closer + if (redir.prefix.length() == longestPrefix && !isClosestContext(redirContext.generic_string(), currentClosestContext, referenceContext)) + continue; + currentClosestContext = redir.context; longestPrefix = redir.prefix.length(); longestPrefixTarget = redir.target; } diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index 33978b1fc..7945f7299 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -176,8 +176,8 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_pres { CompilerStack c; c.setRemappings(vector{"foo=vendor/foo_2.0.0", "vendor/bar:foo=vendor/foo_1.0.0", "bar=vendor/bar"}); - c.addSource("main.sol", "import \"foo/foo.sol\"; import {Bar} \"bar/bar.sol\"; contract Main is Foo2, Bar {} pragma solidity >=0.0;"); - c.addSource("vendor/bar/bar.sol", "import \"foo/foo.sol\"; contract Bar is Foo1 {} pragma solidity >=0.0;"); + c.addSource("main.sol", "import \"foo/foo.sol\"; import {Bar} from \"bar/bar.sol\"; contract Main is Foo2, Bar {} pragma solidity >=0.0;"); + c.addSource("vendor/bar/bar.sol", "import \"foo/foo.sol\"; contract Bar {Foo1 foo;} pragma solidity >=0.0;"); c.addSource("vendor/foo_1.0.0/foo.sol", "contract Foo1 {} pragma solidity >=0.0;"); c.addSource("vendor/foo_2.0.0/foo.sol", "contract Foo2 {} pragma solidity >=0.0;"); BOOST_CHECK(c.compile());