diff --git a/libsolidity/interface/FileReader.cpp b/libsolidity/interface/FileReader.cpp index 47f4d2b5a..c2910d598 100644 --- a/libsolidity/interface/FileReader.cpp +++ b/libsolidity/interface/FileReader.cpp @@ -48,8 +48,7 @@ FileReader::FileReader( vector const& _includePaths, FileSystemPathSet _allowedDirectories ): - m_allowedDirectories(std::move(_allowedDirectories)), - m_sourceCodes() + m_allowedDirectories(std::move(_allowedDirectories)) { setBasePath(_basePath); for (boost::filesystem::path const& includePath: _includePaths) @@ -84,21 +83,6 @@ void FileReader::allowDirectory(boost::filesystem::path _path) m_allowedDirectories.insert(std::move(_path)); } -void FileReader::addOrUpdateFile(boost::filesystem::path const& _path, SourceCode _source) -{ - m_sourceCodes[cliPathToSourceUnitName(_path)] = std::move(_source); -} - -void FileReader::setStdin(SourceCode _source) -{ - m_sourceCodes[""] = std::move(_source); -} - -void FileReader::setSourceUnits(StringMap _sources) -{ - m_sourceCodes = std::move(_sources); -} - ReadCallback::Result FileReader::readFile(string const& _kind, string const& _sourceUnitName) { try @@ -154,8 +138,6 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so // NOTE: we ignore the FileNotFound exception as we manually check above auto contents = readFileAsString(candidates[0]); - solAssert(m_sourceCodes.count(_sourceUnitName) == 0, ""); - m_sourceCodes[_sourceUnitName] = contents; return ReadCallback::Result{true, contents}; } catch (util::Exception const& _exception) @@ -363,4 +345,34 @@ bool FileReader::isUNCPath(boost::filesystem::path const& _path) ); } + +frontend::ReadCallback::Callback FileReaderWithRepository::reader() +{ + return [this](std::string const& _kind, std::string const& _path) { + ReadCallback::Result result = FileReader::readFile(_kind, _path); + if (result.success) + { + solAssert(_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile)); + solAssert(m_sourceCodes.count(_path) == 0, ""); + m_sourceCodes[_path] = result.responseOrErrorMessage; + } + return result; + }; +} + +void FileReaderWithRepository::addOrUpdateFile(boost::filesystem::path const& _path, SourceCode _source) +{ + m_sourceCodes[cliPathToSourceUnitName(_path)] = std::move(_source); +} + +void FileReaderWithRepository::setStdin(SourceCode _source) +{ + m_sourceCodes[""] = std::move(_source); +} + +void FileReaderWithRepository::setSourceUnits(StringMap _sources) +{ + m_sourceCodes = std::move(_sources); +} + } diff --git a/libsolidity/interface/FileReader.h b/libsolidity/interface/FileReader.h index 3892e9826..11a50884d 100644 --- a/libsolidity/interface/FileReader.h +++ b/libsolidity/interface/FileReader.h @@ -35,7 +35,6 @@ namespace solidity::frontend class FileReader { public: - using StringMap = std::map; using PathMap = std::map; using FileSystemPathSet = std::set; @@ -61,22 +60,6 @@ public: void allowDirectory(boost::filesystem::path _path); FileSystemPathSet const& allowedDirectories() const noexcept { return m_allowedDirectories; } - /// @returns all sources by their internal source unit names. - StringMap const& sourceUnits() const noexcept { return m_sourceCodes; } - - /// Resets all sources to the given map of source unit name to source codes. - /// Does not enforce @a allowedDirectories(). - void setSourceUnits(StringMap _sources); - - /// Adds the source code under a source unit name created by normalizing the file path - /// or changes an existing source. - /// Does not enforce @a allowedDirectories(). - void addOrUpdateFile(boost::filesystem::path const& _path, SourceCode _source); - - /// Adds the source code under the source unit name of @a . - /// Does not enforce @a allowedDirectories(). - void setStdin(SourceCode _source); - /// Receives a @p _sourceUnitName that refers to a source unit in compiler's virtual filesystem /// and attempts to interpret it as a path and read the corresponding file from disk. /// The read will only succeed if the canonical path of the file is within one of the @a allowedDirectories(). @@ -86,7 +69,7 @@ public: /// already exists, previous content is discarded. frontend::ReadCallback::Result readFile(std::string const& _kind, std::string const& _sourceUnitName); - frontend::ReadCallback::Callback reader() + virtual frontend::ReadCallback::Callback reader() { return [this](std::string const& _kind, std::string const& _path) { return readFile(_kind, _path); }; } @@ -152,7 +135,41 @@ private: /// list of allowed directories to read files from FileSystemPathSet m_allowedDirectories; +}; +/** + * FileReader with the feature to store the contents of files. + */ +class FileReaderWithRepository: public FileReader +{ +public: + using StringMap = std::map; + + explicit FileReaderWithRepository( + boost::filesystem::path _basePath = {}, + std::vector const& _includePaths = {}, + FileSystemPathSet _allowedDirectories = {} + ): FileReader(_basePath, _includePaths, std::move(_allowedDirectories)) {} + + frontend::ReadCallback::Callback reader() override; + + /// @returns all sources by their internal source unit names. + StringMap const& sourceUnits() const noexcept { return m_sourceCodes; } + + /// Resets all sources to the given map of source unit name to source codes. + /// Does not enforce @a allowedDirectories(). + void setSourceUnits(StringMap _sources); + + /// Adds the source code under a source unit name created by normalizing the file path + /// or changes an existing source. + /// Does not enforce @a allowedDirectories(). + void addOrUpdateFile(boost::filesystem::path const& _path, SourceCode _source); + + /// Adds the source code under the source unit name of @a . + /// Does not enforce @a allowedDirectories(). + void setStdin(SourceCode _source); + +private: /// map of input files to source code strings StringMap m_sourceCodes; }; diff --git a/libsolidity/lsp/FileRepository.h b/libsolidity/lsp/FileRepository.h index b6aa5ee08..07e12c3fd 100644 --- a/libsolidity/lsp/FileRepository.h +++ b/libsolidity/lsp/FileRepository.h @@ -47,7 +47,7 @@ public: private: std::map m_sourceUnitNamesToClientPaths; - frontend::FileReader m_fileReader; + frontend::FileReaderWithRepository m_fileReader; }; } diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 235059a02..ecd463d93 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -925,7 +925,7 @@ void CommandLineInterface::link() librariesReplacements[replacement] = library.second; } - FileReader::StringMap sourceCodes = m_fileReader.sourceUnits(); + FileReaderWithRepository::StringMap sourceCodes = m_fileReader.sourceUnits(); for (auto& src: sourceCodes) { auto end = src.second.end(); diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 951731825..26a9e2319 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -75,7 +75,7 @@ public: void processInput(); CommandLineOptions const& options() const { return m_options; } - FileReader const& fileReader() const { return m_fileReader; } + FileReaderWithRepository const& fileReader() const { return m_fileReader; } std::optional const& standardJsonInput() const { return m_standardJsonInput; } private: @@ -137,7 +137,7 @@ private: std::ostream& m_sout; std::ostream& m_serr; bool m_hasOutput = false; - FileReader m_fileReader; + FileReaderWithRepository m_fileReader; std::optional m_standardJsonInput; std::unique_ptr m_compiler; CommandLineOptions m_options; diff --git a/test/solc/Common.h b/test/solc/Common.h index 3575bea74..def991ec4 100644 --- a/test/solc/Common.h +++ b/test/solc/Common.h @@ -36,7 +36,7 @@ struct OptionsReaderAndMessages { bool success; CommandLineOptions options; - FileReader reader; + FileReaderWithRepository reader; std::optional standardJsonInput; std::string stdoutContent; std::string stderrContent;