Merge pull request #1548 from VoR0220/remappingBugFix

Remapping bug fix
This commit is contained in:
chriseth 2017-01-12 12:02:30 +01:00 committed by GitHub
commit 74d74fb00b
4 changed files with 51 additions and 9 deletions

View File

@ -4,6 +4,7 @@ Features:
* Output: Print assembly in new standardized Solidity assembly format. * Output: Print assembly in new standardized Solidity assembly format.
BugFixes: BugFixes:
* Remappings: Prefer longer context over longer prefix.
* Type checker, code generator: enable access to events of base contracts' names. * Type checker, code generator: enable access to events of base contracts' names.
* Imports: ``import ".dir/a"`` is not a relative path. Relative paths begin with directory ``.`` or ``..``. * Imports: ``import ".dir/a"`` is not a relative path. Relative paths begin with directory ``.`` or ``..``.

View File

@ -509,23 +509,32 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context
}; };
size_t longestPrefix = 0; size_t longestPrefix = 0;
string longestPrefixTarget; size_t longestContext = 0;
string bestMatchTarget;
for (auto const& redir: m_remappings) for (auto const& redir: m_remappings)
{ {
// Skip if we already have a closer match. string context = sanitizePath(redir.context);
if (longestPrefix > 0 && redir.prefix.length() <= longestPrefix) string prefix = sanitizePath(redir.prefix);
// Skip if current context is closer
if (context.length() < longestContext)
continue; continue;
// Skip if redir.context is not a prefix of _context // Skip if redir.context is not a prefix of _context
if (!isPrefixOf(redir.context, _context)) if (!isPrefixOf(context, _context))
continue;
// Skip if we already have a closer prefix match.
if (prefix.length() < longestPrefix && context.length() == longestContext)
continue; continue;
// Skip if the prefix does not match. // Skip if the prefix does not match.
if (!isPrefixOf(redir.prefix, _path)) if (!isPrefixOf(prefix, _path))
continue; continue;
longestPrefix = redir.prefix.length(); longestContext = context.length();
longestPrefixTarget = redir.target; longestPrefix = prefix.length();
bestMatchTarget = sanitizePath(redir.target);
} }
string path = longestPrefixTarget; string path = bestMatchTarget;
path.append(_path.begin() + longestPrefix, _path.end()); path.append(_path.begin() + longestPrefix, _path.end());
return path; return path;
} }

View File

@ -29,6 +29,7 @@
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/filesystem.hpp>
#include <json/json.h> #include <json/json.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/FixedHash.h> #include <libdevcore/FixedHash.h>
@ -234,12 +235,14 @@ private:
bool checkLibraryNameClashes(); bool checkLibraryNameClashes();
/// @returns the absolute path corresponding to @a _path relative to @a _reference. /// @returns the absolute path corresponding to @a _path relative to @a _reference.
std::string absolutePath(std::string const& _path, std::string const& _reference) const; std::string absolutePath(std::string const& _path, std::string const& _reference) const;
/// Helper function to return path converted strings.
std::string sanitizePath(std::string const& _path) const { return boost::filesystem::path(_path).generic_string(); }
/// Compile a single contract and put the result in @a _compiledContracts. /// Compile a single contract and put the result in @a _compiledContracts.
void compileContract( void compileContract(
ContractDefinition const& _contract, ContractDefinition const& _contract,
std::map<ContractDefinition const*, eth::Assembly const*>& _compiledContracts std::map<ContractDefinition const*, eth::Assembly const*>& _compiledContracts
); );
void link(); void link();
Contract const& contract(std::string const& _contractName = "") const; Contract const& contract(std::string const& _contractName = "") const;

View File

@ -172,6 +172,35 @@ BOOST_AUTO_TEST_CASE(filename_with_period)
BOOST_CHECK(!c.compile()); BOOST_CHECK(!c.compile());
} }
BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_preserved)
{
CompilerStack c;
c.setRemappings(vector<string>{"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} 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());
}
BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent)
{
CompilerStack c;
c.setRemappings(vector<string>{"a:x/y/z=d", "a/b:x=e"});
c.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;");
c.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;");
c.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;");
c.addSource("e/y/z/z.sol", "contract E {} pragma solidity >=0.0;");
BOOST_CHECK(c.compile());
CompilerStack d;
d.setRemappings(vector<string>{"a/b:x=e", "a:x/y/z=d"});
d.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;");
d.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;");
d.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;");
d.addSource("e/y/z/z.sol", "contract E {} pragma solidity >=0.0;");
BOOST_CHECK(d.compile());
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }