Add --include-path option

This commit is contained in:
Kamil Śliwak
2021-09-27 13:14:23 +02:00
parent a61a950861
commit c8a7a1da7c
11 changed files with 498 additions and 31 deletions
+56 -6
View File
@@ -24,30 +24,54 @@
#include <boost/algorithm/string/predicate.hpp>
#include <range/v3/range/conversion.hpp>
#include <functional>
using solidity::frontend::ReadCallback;
using solidity::langutil::InternalCompilerError;
using solidity::util::errinfo_comment;
using solidity::util::readFileAsString;
using std::reference_wrapper;
using std::string;
using std::vector;
namespace solidity::frontend
{
FileReader::FileReader(
boost::filesystem::path _basePath,
vector<boost::filesystem::path> const& _includePaths,
FileSystemPathSet _allowedDirectories
):
m_allowedDirectories(std::move(_allowedDirectories)),
m_sourceCodes()
{
setBasePath(_basePath);
for (boost::filesystem::path const& includePath: _includePaths)
addIncludePath(includePath);
for (boost::filesystem::path const& allowedDir: m_allowedDirectories)
solAssert(!allowedDir.empty(), "");
}
void FileReader::setBasePath(boost::filesystem::path const& _path)
{
m_basePath = (_path.empty() ? "" : normalizeCLIPathForVFS(_path));
if (_path.empty())
{
// Empty base path is a special case that does not make sense when include paths are used.
solAssert(m_includePaths.empty(), "");
m_basePath = "";
}
else
m_basePath = normalizeCLIPathForVFS(_path);
}
void FileReader::addIncludePath(boost::filesystem::path const& _path)
{
solAssert(!m_basePath.empty(), "");
solAssert(!_path.empty(), "");
m_includePaths.push_back(normalizeCLIPathForVFS(_path));
}
void FileReader::allowDirectory(boost::filesystem::path _path)
@@ -58,10 +82,7 @@ void FileReader::allowDirectory(boost::filesystem::path _path)
void FileReader::setSource(boost::filesystem::path const& _path, SourceCode _source)
{
boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(_path);
boost::filesystem::path prefix = (m_basePath.empty() ? normalizeCLIPathForVFS(".") : m_basePath);
m_sourceCodes[stripPrefixIfPresent(prefix, normalizedPath).generic_string()] = std::move(_source);
m_sourceCodes[cliPathToSourceUnitName(_path)] = std::move(_source);
}
void FileReader::setStdin(SourceCode _source)
@@ -87,8 +108,20 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
if (strippedSourceUnitName.find("file://") == 0)
strippedSourceUnitName.erase(0, 7);
auto canonicalPath = normalizeCLIPathForVFS(m_basePath / strippedSourceUnitName, SymlinkResolution::Enabled);
vector<reference_wrapper<boost::filesystem::path>> prefixes = {m_basePath};
prefixes += (m_includePaths | ranges::to<vector<reference_wrapper<boost::filesystem::path>>>);
boost::filesystem::path canonicalPath;
for (auto const& prefix: prefixes)
{
canonicalPath = normalizeCLIPathForVFS(prefix / strippedSourceUnitName, SymlinkResolution::Enabled);
if (boost::filesystem::exists(canonicalPath))
break;
}
FileSystemPathSet extraAllowedPaths = {m_basePath.empty() ? "." : m_basePath};
extraAllowedPaths += m_includePaths;
bool isAllowed = false;
for (boost::filesystem::path const& allowedDir: m_allowedDirectories + extraAllowedPaths)
@@ -126,6 +159,23 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
}
}
string FileReader::cliPathToSourceUnitName(boost::filesystem::path const& _cliPath)
{
vector<boost::filesystem::path> prefixes = {m_basePath.empty() ? normalizeCLIPathForVFS(".") : m_basePath};
prefixes += m_includePaths;
boost::filesystem::path normalizedPath = normalizeCLIPathForVFS(_cliPath);
for (boost::filesystem::path const& prefix: prefixes)
if (isPathPrefix(prefix, normalizedPath))
{
// Multiple prefixes can potentially match the path. We take the first one.
normalizedPath = stripPrefixIfPresent(prefix, normalizedPath);
break;
}
return normalizedPath.generic_string();
}
boost::filesystem::path FileReader::normalizeCLIPathForVFS(
boost::filesystem::path const& _path,
SymlinkResolution _symlinkResolution
+17 -3
View File
@@ -44,13 +44,20 @@ public:
Enabled, ///< Follow symbolic links. The path should contain no symlinks.
};
/// Constructs a FileReader with a base path and a set of allowed directories that
/// will be used when requesting files from this file reader instance.
explicit FileReader(boost::filesystem::path _basePath = {}, FileSystemPathSet _allowedDirectories = {});
/// Constructs a FileReader with a base path and sets of include paths and allowed directories
/// that will be used when requesting files from this file reader instance.
explicit FileReader(
boost::filesystem::path _basePath = {},
std::vector<boost::filesystem::path> const& _includePaths = {},
FileSystemPathSet _allowedDirectories = {}
);
void setBasePath(boost::filesystem::path const& _path);
boost::filesystem::path const& basePath() const noexcept { return m_basePath; }
void addIncludePath(boost::filesystem::path const& _path);
std::vector<boost::filesystem::path> const& includePaths() const noexcept { return m_includePaths; }
void allowDirectory(boost::filesystem::path _path);
FileSystemPathSet const& allowedDirectories() const noexcept { return m_allowedDirectories; }
@@ -85,6 +92,10 @@ public:
return [this](std::string const& _kind, std::string const& _path) { return readFile(_kind, _path); };
}
/// Creates a source unit name by normalizing a path given on the command line and, if possible,
/// making it relative to base path or one of the include directories.
std::string cliPathToSourceUnitName(boost::filesystem::path const& _cliPath);
/// Normalizes a filesystem path to make it include all components up to the filesystem root,
/// remove small, inconsequential differences that do not affect the meaning and make it look
/// the same on all platforms (if possible).
@@ -130,6 +141,9 @@ private:
/// Base path, used for resolving relative paths in imports.
boost::filesystem::path m_basePath;
/// Additional directories used for resolving relative paths in imports.
std::vector<boost::filesystem::path> m_includePaths;
/// list of allowed directories to read files from
FileSystemPathSet m_allowedDirectories;