/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 #pragma once #include #include #include #include #include #include #include #include #include #include #include namespace solidity::tools { /** * The Solidity source upgrade tool. It supplies a command line interface * and connects this to a compiler stack that the upgrade logic is facilitated * with. */ class SourceUpgrade { public: /// Parse command line arguments and return false in case of a failure. bool parseArguments(int _argc, char** _argv); /// Prints additional information on the upgrade tool. void printPrologue(); /// Parse / compile files and runs upgrade analysis on them. bool processInput(); private: /// All available upgrade modules enum class Module { ConstructorKeyword, VisibilitySpecifier, AbstractContract, OverridingFunction, VirtualFunction, DotSyntax, NowKeyword, ConstrutorVisibility }; /// Upgrade suite that hosts all available modules. class Suite: public UpgradeSuite { public: void analyze(frontend::SourceUnit const& _sourceUnit) { /// Solidity 0.5.0 if (isActivated(Module::ConstructorKeyword)) ConstructorKeyword{m_changes}.analyze(_sourceUnit); if (isActivated(Module::VisibilitySpecifier)) VisibilitySpecifier{m_changes}.analyze(_sourceUnit); /// Solidity 0.6.0 if (isActivated(Module::AbstractContract)) AbstractContract{m_changes}.analyze(_sourceUnit); if (isActivated(Module::OverridingFunction)) OverridingFunction{m_changes}.analyze(_sourceUnit); if (isActivated(Module::VirtualFunction)) VirtualFunction{m_changes}.analyze(_sourceUnit); /// Solidity 0.7.0 if (isActivated(Module::DotSyntax)) DotSyntax{m_changes}.analyze(_sourceUnit); if (isActivated(Module::NowKeyword)) NowKeyword{m_changes}.analyze(_sourceUnit); if (isActivated(Module::ConstrutorVisibility)) ConstructorVisibility{m_changes}.analyze(_sourceUnit); } void activateModule(Module _module) { m_modules.insert(_module); } void deactivateModules() { m_modules.clear(); } private: bool isActivated(Module _module) const { return m_modules.find(_module) != m_modules.end(); } /// All modules are activated by default. Clear them before activating /// single ones. std::set m_modules = { Module::ConstructorKeyword, Module::VisibilitySpecifier, Module::AbstractContract, Module::OverridingFunction, Module::VirtualFunction, Module::DotSyntax, Module::NowKeyword, Module::ConstrutorVisibility }; }; /// Parses the current sources and runs analyses as well as compilation on /// them if parsing was successful. void tryCompile() const; /// Analyses and upgrades the sources given. The upgrade happens in a loop, /// applying one change at a time, which is run until no applicable changes /// are found any more. Only one change is done at a time and all sources /// are being compiled again after each change. void runUpgrade(); /// Runs upgrade analysis on source and applies upgrades changes to it. /// Returns `true` if there're still changes that can be applied, /// `false` otherwise. bool analyzeAndUpgrade( std::pair const& _sourceCode ); /// Applies the change given to its source code. If no `--dry-run` was /// passed via the commandline, the upgraded source code is written back /// to its file. void applyChange( std::pair const& _sourceCode, UpgradeChange& _change ); /// Prints all errors (excluding warnings) the compiler currently reported. void printErrors() const; /// Prints error and upgrade overview at the end of each full run. void printStatistics() const; /// Reads all input files given and stores sources in the internal data /// structure. Reports errors if files cannot be found. bool readInputFiles(); /// Writes source to file given. bool writeInputFile(std::string const& _path, std::string const& _source); /// Returns a file reader function that fills `m_sources`. frontend::ReadCallback::Callback fileReader(); /// Resets the compiler stack and configures sources to compile. /// Also enables error recovery. void resetCompiler(); /// Resets the compiler stack and configures sources to compile. /// Also enables error recovery. Passes read callback to the compiler stack. void resetCompiler(frontend::ReadCallback::Callback const& _callback); /// Compiler arguments variable map boost::program_options::variables_map m_args; /// Map of input files to source code strings std::map m_sourceCodes; /// Solidity compiler stack std::unique_ptr m_compiler; /// List of allowed directories to read files from std::vector m_allowedDirectories; /// Holds all upgrade modules and source upgrades. Suite m_suite; }; }