CommandLineInterface: Update control flow to accommodate the new way of reporting errors

This commit is contained in:
Kamil Śliwak
2021-10-14 13:45:41 +02:00
parent deb6250916
commit fd5b4e2011
7 changed files with 196 additions and 158 deletions
+36 -34
View File
@@ -404,7 +404,7 @@ void CommandLineInterface::handleGasEstimation(string const& _contract)
}
}
bool CommandLineInterface::readInputFiles()
void CommandLineInterface::readInputFiles()
{
solAssert(!m_standardJsonInput.has_value(), "");
@@ -413,7 +413,7 @@ bool CommandLineInterface::readInputFiles()
m_options.input.mode == InputMode::License ||
m_options.input.mode == InputMode::Version
)
return true;
return;
m_fileReader.setBasePath(m_options.input.basePath);
@@ -501,8 +501,6 @@ bool CommandLineInterface::readInputFiles()
if (m_fileReader.sourceCodes().empty() && !m_standardJsonInput.has_value())
solThrow(CommandLineValidationError, "All specified input files either do not exist or are not regular files.");
return true;
}
map<string, Json::Value> CommandLineInterface::parseAstFromInput()
@@ -568,6 +566,30 @@ void CommandLineInterface::createJson(string const& _fileName, string const& _js
createFile(boost::filesystem::basename(_fileName) + string(".json"), _json);
}
bool CommandLineInterface::run(int _argc, char const* const* _argv)
{
try
{
if (!parseArguments(_argc, _argv))
return false;
readInputFiles();
processInput();
return true;
}
catch (CommandLineError const& _exception)
{
m_hasOutput = true;
// There might be no message in the exception itself if the error output is bulky and has
// already been printed to stderr (this happens e.g. for compiler errors).
if (_exception.what() != ""s)
serr() << _exception.what() << endl;
return false;
}
}
bool CommandLineInterface::parseArguments(int _argc, char const* const* _argv)
{
CommandLineParser parser;
@@ -581,22 +603,13 @@ bool CommandLineInterface::parseArguments(int _argc, char const* const* _argv)
return false;
}
try
{
parser.parse(_argc, _argv);
}
catch (CommandLineValidationError const& _exception)
{
serr() << _exception.what() << endl;
return false;
}
parser.parse(_argc, _argv);
m_options = parser.options();
return true;
}
bool CommandLineInterface::processInput()
void CommandLineInterface::processInput()
{
switch (m_options.input.mode)
{
@@ -619,18 +632,15 @@ bool CommandLineInterface::processInput()
break;
}
case InputMode::Assembler:
if (!assemble(m_options.assembly.inputLanguage, m_options.assembly.targetMachine))
return false;
assemble(m_options.assembly.inputLanguage, m_options.assembly.targetMachine);
break;
case InputMode::Linker:
if (!link())
return false;
link();
writeLinkedFiles();
break;
case InputMode::Compiler:
case InputMode::CompilerWithASTImport:
if (!compile())
return false;
compile();
outputCompilationResults();
}
@@ -651,7 +661,7 @@ void CommandLineInterface::printLicense()
sout() << licenseText << endl;
}
bool CommandLineInterface::compile()
void CommandLineInterface::compile()
{
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, "");
@@ -714,6 +724,8 @@ bool CommandLineInterface::compile()
}
catch (Exception const& _exc)
{
// FIXME: AST import is missing proper validations. This hack catches failing
// assertions and presents them as if they were compiler errors.
solThrow(CommandLineExecutionError, "Failed to import AST: "s + _exc.what());
}
}
@@ -754,8 +766,6 @@ bool CommandLineInterface::compile()
solThrow(CommandLineExecutionError, "");
}
}
return true;
}
void CommandLineInterface::handleCombinedJSON()
@@ -884,7 +894,7 @@ void CommandLineInterface::handleAst()
}
}
bool CommandLineInterface::link()
void CommandLineInterface::link()
{
solAssert(m_options.input.mode == InputMode::Linker, "");
@@ -945,8 +955,6 @@ bool CommandLineInterface::link()
src.second.resize(src.second.size() - 1);
}
m_fileReader.setSources(move(sourceCodes));
return true;
}
void CommandLineInterface::writeLinkedFiles()
@@ -986,7 +994,7 @@ string CommandLineInterface::objectWithLinkRefsHex(evmasm::LinkerObject const& _
return out;
}
bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul::AssemblyStack::Machine _targetMachine)
void CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul::AssemblyStack::Machine _targetMachine)
{
solAssert(m_options.input.mode == InputMode::Assembler, "");
@@ -1072,8 +1080,6 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul:
else
serr() << "No text representation found." << endl;
}
return true;
}
void CommandLineInterface::outputCompilationResults()
@@ -1110,13 +1116,9 @@ void CommandLineInterface::outputCompilationResults()
ret = m_compiler->assemblyString(contract, m_fileReader.sourceCodes());
if (!m_options.output.dir.empty())
{
createFile(m_compiler->filesystemFriendlyName(contract) + (m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"), ret);
}
else
{
sout() << "EVM assembly:" << endl << ret << endl;
}
}
if (m_options.compiler.estimateGas)
+24 -8
View File
@@ -51,12 +51,28 @@ public:
m_options(_options)
{}
/// Parse command line arguments and return false if we should not continue
/// Parses command-line arguments, executes the requested operation and handles validation and
/// execution errors.
/// @returns false if it catches a @p CommandLineValidationError or if the application is
/// expected to exit with a non-zero exit code despite there being no error.
bool run(int _argc, char const* const* _argv);
/// Parses command line arguments and stores the result in @p m_options.
/// @throws CommandLineValidationError if command-line arguments are invalid.
/// @returns false if the application is expected to exit with a non-zero exit code despite
/// there being no error.
bool parseArguments(int _argc, char const* const* _argv);
/// Read the content of all input files and initialize the file reader.
bool readInputFiles();
/// Parse the files, create source code objects, print the output.
bool processInput();
/// Reads the content of all input files and initializes the file reader.
/// @throws CommandLineValidationError if it fails to read the input files (invalid paths,
/// non-existent files, not enough or too many input files, etc.).
void readInputFiles();
/// Executes the requested operation (compilation, assembling, standard JSON, etc.) and prints
/// results to the terminal.
/// @throws CommandLineExecutionError if execution fails due to errors in the input files.
/// @throws CommandLineOutputError if creating output files or writing to them fails.
void processInput();
CommandLineOptions const& options() const { return m_options; }
FileReader const& fileReader() const { return m_fileReader; }
@@ -65,15 +81,15 @@ public:
private:
void printVersion();
void printLicense();
bool compile();
bool link();
void compile();
void link();
void writeLinkedFiles();
/// @returns the ``// <identifier> -> name`` hint for library placeholders.
static std::string libraryPlaceholderHint(std::string const& _libraryName);
/// @returns the full object with library placeholder hints in hex.
static std::string objectWithLinkRefsHex(evmasm::LinkerObject const& _obj);
bool assemble(yul::AssemblyStack::Language _language, yul::AssemblyStack::Machine _targetMachine);
void assemble(yul::AssemblyStack::Language _language, yul::AssemblyStack::Machine _targetMachine);
void outputCompilationResults();
+1 -6
View File
@@ -62,12 +62,7 @@ int main(int argc, char** argv)
{
setDefaultOrCLocale();
solidity::frontend::CommandLineInterface cli(cin, cout, cerr);
bool success =
cli.parseArguments(argc, argv) &&
cli.readInputFiles() &&
cli.processInput();
return success ? 0 : 1;
return cli.run(argc, argv) ? 0 : 1;
}
catch (smtutil::SMTLogicError const& _exception)
{