mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #13162 from ethereum/cleanup_helpers_around_errors
cleaning up helpers around errors
This commit is contained in:
commit
37597f9e88
@ -39,34 +39,6 @@ Error::Error(
|
||||
m_errorId(_errorId),
|
||||
m_type(_type)
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case Type::CodeGenerationError:
|
||||
m_typeName = "CodeGenerationError";
|
||||
break;
|
||||
case Type::DeclarationError:
|
||||
m_typeName = "DeclarationError";
|
||||
break;
|
||||
case Type::DocstringParsingError:
|
||||
m_typeName = "DocstringParsingError";
|
||||
break;
|
||||
case Type::Info:
|
||||
m_typeName = "Info";
|
||||
break;
|
||||
case Type::ParserError:
|
||||
m_typeName = "ParserError";
|
||||
break;
|
||||
case Type::SyntaxError:
|
||||
m_typeName = "SyntaxError";
|
||||
break;
|
||||
case Type::TypeError:
|
||||
m_typeName = "TypeError";
|
||||
break;
|
||||
case Type::Warning:
|
||||
m_typeName = "Warning";
|
||||
break;
|
||||
}
|
||||
|
||||
if (_location.isValid())
|
||||
*this << errinfo_sourceLocation(_location);
|
||||
if (!_secondaryLocation.infos.empty())
|
||||
@ -84,15 +56,3 @@ SecondarySourceLocation const* Error::secondarySourceLocation() const noexcept
|
||||
{
|
||||
return boost::get_error_info<errinfo_secondarySourceLocation>(*this);
|
||||
}
|
||||
|
||||
optional<Error::Severity> Error::severityFromString(string _input)
|
||||
{
|
||||
boost::algorithm::to_lower(_input);
|
||||
boost::algorithm::trim(_input);
|
||||
|
||||
for (Severity severity: {Severity::Error, Severity::Warning, Severity::Info})
|
||||
if (_input == formatErrorSeverityLowercase(severity))
|
||||
return severity;
|
||||
|
||||
return nullopt;
|
||||
}
|
||||
|
@ -31,11 +31,13 @@
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/facilities/empty.hpp>
|
||||
#include <boost/preprocessor/facilities/overload.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
|
||||
namespace solidity::langutil
|
||||
{
|
||||
@ -174,6 +176,15 @@ public:
|
||||
ParserError,
|
||||
TypeError,
|
||||
SyntaxError,
|
||||
IOError,
|
||||
FatalError,
|
||||
JSONError,
|
||||
InternalCompilerError,
|
||||
CompilerError,
|
||||
Exception,
|
||||
UnimplementedFeatureError,
|
||||
YulException,
|
||||
SMTLogicException,
|
||||
Warning,
|
||||
Info
|
||||
};
|
||||
@ -195,7 +206,6 @@ public:
|
||||
|
||||
ErrorId errorId() const { return m_errorId; }
|
||||
Type type() const { return m_type; }
|
||||
std::string const& typeName() const { return m_typeName; }
|
||||
|
||||
SourceLocation const* sourceLocation() const noexcept;
|
||||
SecondarySourceLocation const* secondarySourceLocation() const noexcept;
|
||||
@ -211,11 +221,19 @@ public:
|
||||
|
||||
static constexpr Severity errorSeverity(Type _type)
|
||||
{
|
||||
if (_type == Type::Info)
|
||||
return Severity::Info;
|
||||
if (_type == Type::Warning)
|
||||
return Severity::Warning;
|
||||
return Severity::Error;
|
||||
switch (_type)
|
||||
{
|
||||
case Type::Info: return Severity::Info;
|
||||
case Type::Warning: return Severity::Warning;
|
||||
default: return Severity::Error;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr Severity errorSeverityOrType(std::variant<Error::Type, Error::Severity> _typeOrSeverity)
|
||||
{
|
||||
if (std::holds_alternative<Error::Type>(_typeOrSeverity))
|
||||
return errorSeverity(std::get<Error::Type>(_typeOrSeverity));
|
||||
return std::get<Error::Severity>(_typeOrSeverity);
|
||||
}
|
||||
|
||||
static bool isError(Severity _severity)
|
||||
@ -238,35 +256,57 @@ public:
|
||||
|
||||
static std::string formatErrorSeverity(Severity _severity)
|
||||
{
|
||||
if (_severity == Severity::Info)
|
||||
return "Info";
|
||||
if (_severity == Severity::Warning)
|
||||
return "Warning";
|
||||
solAssert(isError(_severity), "");
|
||||
return "Error";
|
||||
switch (_severity)
|
||||
{
|
||||
case Severity::Info: return "Info";
|
||||
case Severity::Warning: return "Warning";
|
||||
case Severity::Error: return "Error";
|
||||
}
|
||||
util::unreachable();
|
||||
}
|
||||
|
||||
static std::string formatErrorType(Type _type)
|
||||
{
|
||||
switch (_type)
|
||||
{
|
||||
case Type::IOError: return "IOError";
|
||||
case Type::FatalError: return "FatalError";
|
||||
case Type::JSONError: return "JSONError";
|
||||
case Type::InternalCompilerError: return "InternalCompilerError";
|
||||
case Type::CompilerError: return "CompilerError";
|
||||
case Type::Exception: return "Exception";
|
||||
case Type::CodeGenerationError: return "CodeGenerationError";
|
||||
case Type::DeclarationError: return "DeclarationError";
|
||||
case Type::DocstringParsingError: return "DocstringParsingError";
|
||||
case Type::ParserError: return "ParserError";
|
||||
case Type::SyntaxError: return "SyntaxError";
|
||||
case Type::TypeError: return "TypeError";
|
||||
case Type::UnimplementedFeatureError: return "UnimplementedFeatureError";
|
||||
case Type::YulException: return "YulException";
|
||||
case Type::SMTLogicException: return "SMTLogicException";
|
||||
case Type::Warning: return "Warning";
|
||||
case Type::Info: return "Info";
|
||||
}
|
||||
util::unreachable();
|
||||
}
|
||||
|
||||
static std::string formatTypeOrSeverity(std::variant<Error::Type, Error::Severity> _typeOrSeverity)
|
||||
{
|
||||
if (std::holds_alternative<Error::Type>(_typeOrSeverity))
|
||||
return formatErrorType(std::get<Error::Type>(_typeOrSeverity));
|
||||
return formatErrorSeverity(std::get<Error::Severity>(_typeOrSeverity));
|
||||
}
|
||||
|
||||
static std::string formatErrorSeverityLowercase(Severity _severity)
|
||||
{
|
||||
switch (_severity)
|
||||
{
|
||||
case Severity::Info:
|
||||
return "info";
|
||||
case Severity::Warning:
|
||||
return "warning";
|
||||
case Severity::Error:
|
||||
solAssert(isError(_severity), "");
|
||||
return "error";
|
||||
}
|
||||
solAssert(false, "");
|
||||
std::string severityValue = formatErrorSeverity(_severity);
|
||||
boost::algorithm::to_lower(severityValue);
|
||||
return severityValue;
|
||||
}
|
||||
|
||||
static std::optional<Severity> severityFromString(std::string _input);
|
||||
|
||||
private:
|
||||
ErrorId m_errorId;
|
||||
Type m_type;
|
||||
std::string m_typeName;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <variant>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
@ -30,7 +31,7 @@ using namespace solidity::langutil;
|
||||
SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
util::Exception const& _exception,
|
||||
string _severity
|
||||
std::variant<Error::Type, Error::Severity> _typeOrSeverity
|
||||
)
|
||||
{
|
||||
SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
|
||||
@ -44,16 +45,16 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
|
||||
for (auto const& info: secondaryLocation->infos)
|
||||
secondary.emplace_back(extract(_charStreamProvider, &info.second, info.first));
|
||||
|
||||
return Message{std::move(primary), _severity, std::move(secondary), nullopt};
|
||||
return Message{std::move(primary), _typeOrSeverity, std::move(secondary), nullopt};
|
||||
}
|
||||
|
||||
SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
Error const& _error
|
||||
Error const& _error,
|
||||
std::variant<Error::Type, Error::Severity> _typeOrSeverity
|
||||
)
|
||||
{
|
||||
string severity = Error::formatErrorSeverity(Error::errorSeverity(_error.type()));
|
||||
Message message = extract(_charStreamProvider, _error, severity);
|
||||
Message message = extract(_charStreamProvider, static_cast<util::Exception>(_error), _typeOrSeverity);
|
||||
message.errorId = _error.errorId();
|
||||
return message;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
|
||||
namespace solidity::langutil
|
||||
{
|
||||
@ -55,12 +56,21 @@ namespace SourceReferenceExtractor
|
||||
struct Message
|
||||
{
|
||||
SourceReference primary;
|
||||
std::string severity; // "Error", "Warning", "Info", ...
|
||||
std::variant<Error::Type, Error::Severity> _typeOrSeverity;
|
||||
std::vector<SourceReference> secondary;
|
||||
std::optional<ErrorId> errorId;
|
||||
};
|
||||
|
||||
Message extract(CharStreamProvider const& _charStreamProvider, util::Exception const& _exception, std::string _severity);
|
||||
Message extract(
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
util::Exception const& _exception,
|
||||
std::variant<Error::Type, Error::Severity> _typeOrSeverity
|
||||
);
|
||||
Message extract(
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
Error const& _error,
|
||||
std::variant<Error::Type, Error::Severity> _typeOrSeverity
|
||||
);
|
||||
Message extract(CharStreamProvider const& _charStreamProvider, Error const& _error);
|
||||
SourceReference extract(CharStreamProvider const& _charStreamProvider, SourceLocation const* _location, std::string message = "");
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <libsolutil/UTF8.h>
|
||||
#include <iomanip>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
@ -65,19 +66,18 @@ AnsiColorized SourceReferenceFormatter::frameColored() const
|
||||
return AnsiColorized(m_stream, m_colored, {BOLD, BLUE});
|
||||
}
|
||||
|
||||
AnsiColorized SourceReferenceFormatter::errorColored(optional<Error::Severity> _severity) const
|
||||
AnsiColorized SourceReferenceFormatter::errorColored(Error::Severity _severity) const
|
||||
{
|
||||
// We used to color messages of any severity as errors so this seems like a good default
|
||||
// for cases where severity cannot be determined.
|
||||
char const* textColor = RED;
|
||||
|
||||
if (_severity.has_value())
|
||||
switch (_severity.value())
|
||||
{
|
||||
case Error::Severity::Error: textColor = RED; break;
|
||||
case Error::Severity::Warning: textColor = YELLOW; break;
|
||||
case Error::Severity::Info: textColor = WHITE; break;
|
||||
}
|
||||
switch (_severity)
|
||||
{
|
||||
case Error::Severity::Error: textColor = RED; break;
|
||||
case Error::Severity::Warning: textColor = YELLOW; break;
|
||||
case Error::Severity::Info: textColor = WHITE; break;
|
||||
}
|
||||
|
||||
return AnsiColorized(m_stream, m_colored, {BOLD, textColor});
|
||||
}
|
||||
@ -178,13 +178,12 @@ void SourceReferenceFormatter::printSourceLocation(SourceReference const& _ref)
|
||||
|
||||
void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg)
|
||||
{
|
||||
// exception header line
|
||||
optional<Error::Severity> severity = Error::severityFromString(_msg.severity);
|
||||
errorColored(severity) << _msg.severity;
|
||||
if (m_withErrorIds && _msg.errorId.has_value())
|
||||
errorColored(severity) << " (" << _msg.errorId.value().error << ")";
|
||||
messageColored() << ": " << _msg.primary.message << '\n';
|
||||
errorColored(Error::errorSeverityOrType(_msg._typeOrSeverity)) << Error::formatTypeOrSeverity(_msg._typeOrSeverity);
|
||||
|
||||
if (m_withErrorIds && _msg.errorId.has_value())
|
||||
errorColored(Error::errorSeverityOrType(_msg._typeOrSeverity)) << " (" << _msg.errorId.value().error << ")";
|
||||
|
||||
messageColored() << ": " << _msg.primary.message << '\n';
|
||||
printSourceLocation(_msg.primary);
|
||||
|
||||
for (auto const& secondary: _msg.secondary)
|
||||
@ -197,7 +196,12 @@ void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtracto
|
||||
m_stream << '\n';
|
||||
}
|
||||
|
||||
void SourceReferenceFormatter::printExceptionInformation(util::Exception const& _exception, std::string const& _severity)
|
||||
void SourceReferenceFormatter::printExceptionInformation(util::Exception const& _exception, Error::Type _type)
|
||||
{
|
||||
printExceptionInformation(SourceReferenceExtractor::extract(m_charStreamProvider, _exception, _type));
|
||||
}
|
||||
|
||||
void SourceReferenceFormatter::printExceptionInformation(util::Exception const& _exception, Error::Severity _severity)
|
||||
{
|
||||
printExceptionInformation(SourceReferenceExtractor::extract(m_charStreamProvider, _exception, _severity));
|
||||
}
|
||||
@ -210,5 +214,11 @@ void SourceReferenceFormatter::printErrorInformation(ErrorList const& _errors)
|
||||
|
||||
void SourceReferenceFormatter::printErrorInformation(Error const& _error)
|
||||
{
|
||||
printExceptionInformation(SourceReferenceExtractor::extract(m_charStreamProvider, _error));
|
||||
SourceReferenceExtractor::Message message =
|
||||
SourceReferenceExtractor::extract(
|
||||
m_charStreamProvider,
|
||||
_error,
|
||||
Error::errorSeverity(_error.type())
|
||||
);
|
||||
printExceptionInformation(message);
|
||||
}
|
||||
|
@ -52,13 +52,14 @@ public:
|
||||
/// Prints source location if it is given.
|
||||
void printSourceLocation(SourceReference const& _ref);
|
||||
void printExceptionInformation(SourceReferenceExtractor::Message const& _msg);
|
||||
void printExceptionInformation(util::Exception const& _exception, std::string const& _severity);
|
||||
void printExceptionInformation(util::Exception const& _exception, Error::Type _type);
|
||||
void printExceptionInformation(util::Exception const& _exception, Error::Severity _severity);
|
||||
void printErrorInformation(langutil::ErrorList const& _errors);
|
||||
void printErrorInformation(Error const& _error);
|
||||
|
||||
static std::string formatExceptionInformation(
|
||||
util::Exception const& _exception,
|
||||
std::string const& _name,
|
||||
Error::Type _type,
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
bool _colored = false,
|
||||
bool _withErrorIds = false
|
||||
@ -66,7 +67,21 @@ public:
|
||||
{
|
||||
std::ostringstream errorOutput;
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
|
||||
formatter.printExceptionInformation(_exception, _name);
|
||||
formatter.printExceptionInformation(_exception, _type);
|
||||
return errorOutput.str();
|
||||
}
|
||||
|
||||
static std::string formatExceptionInformation(
|
||||
util::Exception const& _exception,
|
||||
Error::Severity _severity,
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
bool _colored = false,
|
||||
bool _withErrorIds = false
|
||||
)
|
||||
{
|
||||
std::ostringstream errorOutput;
|
||||
SourceReferenceFormatter formatter(errorOutput, _charStreamProvider, _colored, _withErrorIds);
|
||||
formatter.printExceptionInformation(_exception, _severity);
|
||||
return errorOutput.str();
|
||||
}
|
||||
|
||||
@ -77,7 +92,7 @@ public:
|
||||
{
|
||||
return formatExceptionInformation(
|
||||
_error,
|
||||
Error::formatErrorSeverity(Error::errorSeverity(_error.type())),
|
||||
Error::errorSeverity(_error.type()),
|
||||
_charStreamProvider
|
||||
);
|
||||
}
|
||||
@ -87,7 +102,7 @@ public:
|
||||
private:
|
||||
util::AnsiColorized normalColored() const;
|
||||
util::AnsiColorized frameColored() const;
|
||||
util::AnsiColorized errorColored(std::optional<langutil::Error::Severity> _severity) const;
|
||||
util::AnsiColorized errorColored(langutil::Error::Severity _severity) const;
|
||||
util::AnsiColorized messageColored() const;
|
||||
util::AnsiColorized secondaryColored() const;
|
||||
util::AnsiColorized highlightColored() const;
|
||||
|
@ -54,8 +54,7 @@ namespace
|
||||
{
|
||||
|
||||
Json::Value formatError(
|
||||
Error::Severity _severity,
|
||||
string const& _type,
|
||||
Error::Type _type,
|
||||
string const& _component,
|
||||
string const& _message,
|
||||
string const& _formattedMessage = "",
|
||||
@ -64,9 +63,9 @@ Json::Value formatError(
|
||||
)
|
||||
{
|
||||
Json::Value error{Json::objectValue};
|
||||
error["type"] = _type;
|
||||
error["type"] = Error::formatErrorType(_type);
|
||||
error["component"] = _component;
|
||||
error["severity"] = Error::formatErrorSeverityLowercase(_severity);
|
||||
error["severity"] = Error::formatErrorSeverityLowercase(Error::errorSeverity(_type));
|
||||
error["message"] = _message;
|
||||
error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message;
|
||||
if (_sourceLocation.isObject())
|
||||
@ -76,11 +75,11 @@ Json::Value formatError(
|
||||
return error;
|
||||
}
|
||||
|
||||
Json::Value formatFatalError(string const& _type, string const& _message)
|
||||
Json::Value formatFatalError(Error::Type _type, string const& _message)
|
||||
{
|
||||
Json::Value output{Json::objectValue};
|
||||
output["errors"] = Json::arrayValue;
|
||||
output["errors"].append(formatError(Error::Severity::Error, _type, "general", _message));
|
||||
output["errors"].append(formatError(_type, "general", _message));
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -114,8 +113,7 @@ Json::Value formatSecondarySourceLocation(SecondarySourceLocation const* _second
|
||||
Json::Value formatErrorWithException(
|
||||
CharStreamProvider const& _charStreamProvider,
|
||||
util::Exception const& _exception,
|
||||
Error::Severity _severity,
|
||||
string const& _type,
|
||||
Error::Type _type,
|
||||
string const& _component,
|
||||
string const& _message,
|
||||
optional<ErrorId> _errorId = nullopt
|
||||
@ -126,7 +124,9 @@ Json::Value formatErrorWithException(
|
||||
string formattedMessage = SourceReferenceFormatter::formatExceptionInformation(
|
||||
_exception,
|
||||
_type,
|
||||
_charStreamProvider
|
||||
_charStreamProvider,
|
||||
false, // colored
|
||||
false // _withErrorIds
|
||||
);
|
||||
|
||||
if (string const* description = _exception.comment())
|
||||
@ -135,7 +135,6 @@ Json::Value formatErrorWithException(
|
||||
message = _message;
|
||||
|
||||
Json::Value error = formatError(
|
||||
_severity,
|
||||
_type,
|
||||
_component,
|
||||
message,
|
||||
@ -410,11 +409,11 @@ Json::Value collectEVMObject(
|
||||
std::optional<Json::Value> checkKeys(Json::Value const& _input, set<string> const& _keys, string const& _name)
|
||||
{
|
||||
if (!!_input && !_input.isObject())
|
||||
return formatFatalError("JSONError", "\"" + _name + "\" must be an object");
|
||||
return formatFatalError(Error::Type::JSONError, "\"" + _name + "\" must be an object");
|
||||
|
||||
for (auto const& member: _input.getMemberNames())
|
||||
if (!_keys.count(member))
|
||||
return formatFatalError("JSONError", "Unknown key \"" + member + "\"");
|
||||
return formatFatalError(Error::Type::JSONError, "Unknown key \"" + member + "\"");
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
@ -466,7 +465,7 @@ std::optional<Json::Value> checkOptimizerDetail(Json::Value const& _details, std
|
||||
if (_details.isMember(_name))
|
||||
{
|
||||
if (!_details[_name].isBool())
|
||||
return formatFatalError("JSONError", "\"settings.optimizer.details." + _name + "\" must be Boolean");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.optimizer.details." + _name + "\" must be Boolean");
|
||||
_setting = _details[_name].asBool();
|
||||
}
|
||||
return {};
|
||||
@ -485,7 +484,7 @@ std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details
|
||||
catch (yul::OptimizerException const& _exception)
|
||||
{
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"Invalid optimizer step sequence in \"settings.optimizer.details." + _name + "\": " + _exception.what()
|
||||
);
|
||||
}
|
||||
@ -500,7 +499,7 @@ std::optional<Json::Value> checkOptimizerDetailSteps(Json::Value const& _details
|
||||
solAssert(_cleanupSetting == OptimiserSettings::DefaultYulOptimiserCleanupSteps);
|
||||
}
|
||||
else
|
||||
return formatFatalError("JSONError", "\"settings.optimizer.details." + _name + "\" must be a string");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.optimizer.details." + _name + "\" must be a string");
|
||||
|
||||
}
|
||||
return {};
|
||||
@ -511,11 +510,11 @@ std::optional<Json::Value> checkMetadataKeys(Json::Value const& _input)
|
||||
if (_input.isObject())
|
||||
{
|
||||
if (_input.isMember("useLiteralContent") && !_input["useLiteralContent"].isBool())
|
||||
return formatFatalError("JSONError", "\"settings.metadata.useLiteralContent\" must be Boolean");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.metadata.useLiteralContent\" must be Boolean");
|
||||
|
||||
static set<string> hashes{"ipfs", "bzzr1", "none"};
|
||||
if (_input.isMember("bytecodeHash") && !hashes.count(_input["bytecodeHash"].asString()))
|
||||
return formatFatalError("JSONError", "\"settings.metadata.bytecodeHash\" must be \"ipfs\", \"bzzr1\" or \"none\"");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.metadata.bytecodeHash\" must be \"ipfs\", \"bzzr1\" or \"none\"");
|
||||
}
|
||||
static set<string> keys{"useLiteralContent", "bytecodeHash"};
|
||||
return checkKeys(_input, keys, "settings.metadata");
|
||||
@ -524,7 +523,7 @@ std::optional<Json::Value> checkMetadataKeys(Json::Value const& _input)
|
||||
std::optional<Json::Value> checkOutputSelection(Json::Value const& _outputSelection)
|
||||
{
|
||||
if (!!_outputSelection && !_outputSelection.isObject())
|
||||
return formatFatalError("JSONError", "\"settings.outputSelection\" must be an object");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.outputSelection\" must be an object");
|
||||
|
||||
for (auto const& sourceName: _outputSelection.getMemberNames())
|
||||
{
|
||||
@ -532,7 +531,7 @@ std::optional<Json::Value> checkOutputSelection(Json::Value const& _outputSelect
|
||||
|
||||
if (!sourceVal.isObject())
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"\"settings.outputSelection." + sourceName + "\" must be an object"
|
||||
);
|
||||
|
||||
@ -542,7 +541,7 @@ std::optional<Json::Value> checkOutputSelection(Json::Value const& _outputSelect
|
||||
|
||||
if (!contractVal.isArray())
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"\"settings.outputSelection." +
|
||||
sourceName +
|
||||
"." +
|
||||
@ -553,7 +552,7 @@ std::optional<Json::Value> checkOutputSelection(Json::Value const& _outputSelect
|
||||
for (auto const& output: contractVal)
|
||||
if (!output.isString())
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"\"settings.outputSelection." +
|
||||
sourceName +
|
||||
"." +
|
||||
@ -578,7 +577,7 @@ std::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value
|
||||
if (_jsonInput.isMember("enabled"))
|
||||
{
|
||||
if (!_jsonInput["enabled"].isBool())
|
||||
return formatFatalError("JSONError", "The \"enabled\" setting must be a Boolean.");
|
||||
return formatFatalError(Error::Type::JSONError, "The \"enabled\" setting must be a Boolean.");
|
||||
|
||||
if (_jsonInput["enabled"].asBool())
|
||||
settings = OptimiserSettings::standard();
|
||||
@ -587,7 +586,7 @@ std::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value
|
||||
if (_jsonInput.isMember("runs"))
|
||||
{
|
||||
if (!_jsonInput["runs"].isUInt())
|
||||
return formatFatalError("JSONError", "The \"runs\" setting must be an unsigned number.");
|
||||
return formatFatalError(Error::Type::JSONError, "The \"runs\" setting must be an unsigned number.");
|
||||
settings.expectedExecutionsPerDeployment = _jsonInput["runs"].asUInt();
|
||||
}
|
||||
|
||||
@ -617,7 +616,7 @@ std::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value
|
||||
if (details.isMember("yulDetails"))
|
||||
{
|
||||
if (!settings.runYulOptimiser)
|
||||
return formatFatalError("JSONError", "\"Providing yulDetails requires Yul optimizer to be enabled.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"Providing yulDetails requires Yul optimizer to be enabled.");
|
||||
|
||||
if (auto result = checkKeys(details["yulDetails"], {"stackAllocation", "optimizerSteps"}, "settings.optimizer.details.yulDetails"))
|
||||
return *result;
|
||||
@ -638,7 +637,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
InputsAndSettings ret;
|
||||
|
||||
if (!_input.isObject())
|
||||
return formatFatalError("JSONError", "Input is not a JSON object.");
|
||||
return formatFatalError(Error::Type::JSONError, "Input is not a JSON object.");
|
||||
|
||||
if (auto result = checkRootKeys(_input))
|
||||
return *result;
|
||||
@ -648,10 +647,10 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
Json::Value const& sources = _input["sources"];
|
||||
|
||||
if (!sources.isObject() && !sources.isNull())
|
||||
return formatFatalError("JSONError", "\"sources\" is not a JSON object.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"sources\" is not a JSON object.");
|
||||
|
||||
if (sources.empty())
|
||||
return formatFatalError("JSONError", "No input sources specified.");
|
||||
return formatFatalError(Error::Type::JSONError, "No input sources specified.");
|
||||
|
||||
ret.errors = Json::arrayValue;
|
||||
|
||||
@ -670,8 +669,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
string content = sources[sourceName]["content"].asString();
|
||||
if (!hash.empty() && !hashMatchesContent(hash, content))
|
||||
ret.errors.append(formatError(
|
||||
Error::Severity::Error,
|
||||
"IOError",
|
||||
Error::Type::IOError,
|
||||
"general",
|
||||
"Mismatch between content and supplied hash for \"" + sourceName + "\""
|
||||
));
|
||||
@ -681,22 +679,21 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
else if (sources[sourceName]["urls"].isArray())
|
||||
{
|
||||
if (!m_readFile)
|
||||
return formatFatalError("JSONError", "No import callback supplied, but URL is requested.");
|
||||
return formatFatalError(Error::Type::JSONError, "No import callback supplied, but URL is requested.");
|
||||
|
||||
bool found = false;
|
||||
vector<string> failures;
|
||||
bool found = false;
|
||||
|
||||
for (auto const& url: sources[sourceName]["urls"])
|
||||
{
|
||||
if (!url.isString())
|
||||
return formatFatalError("JSONError", "URL must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "URL must be a string.");
|
||||
ReadCallback::Result result = m_readFile(ReadCallback::kindString(ReadCallback::Kind::ReadFile), url.asString());
|
||||
if (result.success)
|
||||
{
|
||||
if (!hash.empty() && !hashMatchesContent(hash, result.responseOrErrorMessage))
|
||||
ret.errors.append(formatError(
|
||||
Error::Severity::Error,
|
||||
"IOError",
|
||||
Error::Type::IOError,
|
||||
"general",
|
||||
"Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.asString() + "\""
|
||||
));
|
||||
@ -715,15 +712,14 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
/// If the import succeeded, let mark all the others as warnings, otherwise all of them are errors.
|
||||
ret.errors.append(formatError(
|
||||
found ? Error::Severity::Warning : Error::Severity::Error,
|
||||
"IOError",
|
||||
found ? Error::Type::Warning : Error::Type::IOError,
|
||||
"general",
|
||||
failure
|
||||
));
|
||||
}
|
||||
}
|
||||
else
|
||||
return formatFatalError("JSONError", "Invalid input source specified.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid input source specified.");
|
||||
}
|
||||
|
||||
Json::Value const& auxInputs = _input["auxiliaryInput"];
|
||||
@ -737,7 +733,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (!!smtlib2Responses)
|
||||
{
|
||||
if (!smtlib2Responses.isObject())
|
||||
return formatFatalError("JSONError", "\"auxiliaryInput.smtlib2responses\" must be an object.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"auxiliaryInput.smtlib2responses\" must be an object.");
|
||||
|
||||
for (auto const& hashString: smtlib2Responses.getMemberNames())
|
||||
{
|
||||
@ -748,12 +744,12 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
}
|
||||
catch (util::BadHexCharacter const&)
|
||||
{
|
||||
return formatFatalError("JSONError", "Invalid hex encoding of SMTLib2 auxiliary input.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid hex encoding of SMTLib2 auxiliary input.");
|
||||
}
|
||||
|
||||
if (!smtlib2Responses[hashString].isString())
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"\"smtlib2Responses." + hashString + "\" must be a string."
|
||||
);
|
||||
|
||||
@ -770,10 +766,10 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (settings.isMember("stopAfter"))
|
||||
{
|
||||
if (!settings["stopAfter"].isString())
|
||||
return formatFatalError("JSONError", "\"settings.stopAfter\" must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.stopAfter\" must be a string.");
|
||||
|
||||
if (settings["stopAfter"].asString() != "parsing")
|
||||
return formatFatalError("JSONError", "Invalid value for \"settings.stopAfter\". Only valid value is \"parsing\".");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid value for \"settings.stopAfter\". Only valid value is \"parsing\".");
|
||||
|
||||
ret.stopAfter = CompilerStack::State::Parsed;
|
||||
}
|
||||
@ -781,24 +777,24 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (settings.isMember("parserErrorRecovery"))
|
||||
{
|
||||
if (!settings["parserErrorRecovery"].isBool())
|
||||
return formatFatalError("JSONError", "\"settings.parserErrorRecovery\" must be a Boolean.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.parserErrorRecovery\" must be a Boolean.");
|
||||
ret.parserErrorRecovery = settings["parserErrorRecovery"].asBool();
|
||||
}
|
||||
|
||||
if (settings.isMember("viaIR"))
|
||||
{
|
||||
if (!settings["viaIR"].isBool())
|
||||
return formatFatalError("JSONError", "\"settings.viaIR\" must be a Boolean.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.viaIR\" must be a Boolean.");
|
||||
ret.viaIR = settings["viaIR"].asBool();
|
||||
}
|
||||
|
||||
if (settings.isMember("evmVersion"))
|
||||
{
|
||||
if (!settings["evmVersion"].isString())
|
||||
return formatFatalError("JSONError", "evmVersion must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "evmVersion must be a string.");
|
||||
std::optional<langutil::EVMVersion> version = langutil::EVMVersion::fromString(settings["evmVersion"].asString());
|
||||
if (!version)
|
||||
return formatFatalError("JSONError", "Invalid EVM version requested.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid EVM version requested.");
|
||||
ret.evmVersion = *version;
|
||||
}
|
||||
|
||||
@ -810,13 +806,13 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (settings["debug"].isMember("revertStrings"))
|
||||
{
|
||||
if (!settings["debug"]["revertStrings"].isString())
|
||||
return formatFatalError("JSONError", "settings.debug.revertStrings must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.debug.revertStrings must be a string.");
|
||||
std::optional<RevertStrings> revertStrings = revertStringsFromString(settings["debug"]["revertStrings"].asString());
|
||||
if (!revertStrings)
|
||||
return formatFatalError("JSONError", "Invalid value for settings.debug.revertStrings.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid value for settings.debug.revertStrings.");
|
||||
if (*revertStrings == RevertStrings::VerboseDebug)
|
||||
return formatFatalError(
|
||||
"UnimplementedFeatureError",
|
||||
Error::Type::UnimplementedFeatureError,
|
||||
"Only \"default\", \"strip\" and \"debug\" are implemented for settings.debug.revertStrings for now."
|
||||
);
|
||||
ret.revertStrings = *revertStrings;
|
||||
@ -825,7 +821,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (settings["debug"].isMember("debugInfo"))
|
||||
{
|
||||
if (!settings["debug"]["debugInfo"].isArray())
|
||||
return formatFatalError("JSONError", "settings.debug.debugInfo must be an array.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.debug.debugInfo must be an array.");
|
||||
|
||||
vector<string> components;
|
||||
for (Json::Value const& arrayValue: settings["debug"]["debugInfo"])
|
||||
@ -836,11 +832,11 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
true /* _acceptWildcards */
|
||||
);
|
||||
if (!debugInfoSelection.has_value())
|
||||
return formatFatalError("JSONError", "Invalid value in settings.debug.debugInfo.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid value in settings.debug.debugInfo.");
|
||||
|
||||
if (debugInfoSelection->snippet && !debugInfoSelection->location)
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"To use 'snippet' with settings.debug.debugInfo you must select also 'location'."
|
||||
);
|
||||
|
||||
@ -849,16 +845,16 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
}
|
||||
|
||||
if (settings.isMember("remappings") && !settings["remappings"].isArray())
|
||||
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings.");
|
||||
|
||||
for (auto const& remapping: settings.get("remappings", Json::Value()))
|
||||
{
|
||||
if (!remapping.isString())
|
||||
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings");
|
||||
return formatFatalError(Error::Type::JSONError, "\"settings.remappings\" must be an array of strings");
|
||||
if (auto r = ImportRemapper::parseRemapping(remapping.asString()))
|
||||
ret.remappings.emplace_back(std::move(*r));
|
||||
else
|
||||
return formatFatalError("JSONError", "Invalid remapping: \"" + remapping.asString() + "\"");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid remapping: \"" + remapping.asString() + "\"");
|
||||
}
|
||||
|
||||
if (settings.isMember("optimizer"))
|
||||
@ -872,27 +868,27 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
|
||||
Json::Value jsonLibraries = settings.get("libraries", Json::Value(Json::objectValue));
|
||||
if (!jsonLibraries.isObject())
|
||||
return formatFatalError("JSONError", "\"libraries\" is not a JSON object.");
|
||||
return formatFatalError(Error::Type::JSONError, "\"libraries\" is not a JSON object.");
|
||||
for (auto const& sourceName: jsonLibraries.getMemberNames())
|
||||
{
|
||||
auto const& jsonSourceName = jsonLibraries[sourceName];
|
||||
if (!jsonSourceName.isObject())
|
||||
return formatFatalError("JSONError", "Library entry is not a JSON object.");
|
||||
return formatFatalError(Error::Type::JSONError, "Library entry is not a JSON object.");
|
||||
for (auto const& library: jsonSourceName.getMemberNames())
|
||||
{
|
||||
if (!jsonSourceName[library].isString())
|
||||
return formatFatalError("JSONError", "Library address must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "Library address must be a string.");
|
||||
string address = jsonSourceName[library].asString();
|
||||
|
||||
if (!boost::starts_with(address, "0x"))
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"Library address is not prefixed with \"0x\"."
|
||||
);
|
||||
|
||||
if (address.length() != 42)
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"Library address is of invalid length."
|
||||
);
|
||||
|
||||
@ -903,7 +899,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
catch (util::BadHexCharacter const&)
|
||||
{
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"Invalid library address (\"" + address + "\") supplied."
|
||||
);
|
||||
}
|
||||
@ -936,7 +932,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
|
||||
if (ret.stopAfter != CompilerStack::State::CompilationSuccessful && isBinaryRequested(ret.outputSelection))
|
||||
return formatFatalError(
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"Requested output selection conflicts with \"settings.stopAfter\"."
|
||||
);
|
||||
|
||||
@ -949,29 +945,29 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
auto const& sources = modelCheckerSettings["contracts"];
|
||||
if (!sources.isObject() && !sources.isNull())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.contracts is not a JSON object.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.contracts is not a JSON object.");
|
||||
|
||||
map<string, set<string>> sourceContracts;
|
||||
for (auto const& source: sources.getMemberNames())
|
||||
{
|
||||
if (source.empty())
|
||||
return formatFatalError("JSONError", "Source name cannot be empty.");
|
||||
return formatFatalError(Error::Type::JSONError, "Source name cannot be empty.");
|
||||
|
||||
auto const& contracts = sources[source];
|
||||
if (!contracts.isArray())
|
||||
return formatFatalError("JSONError", "Source contracts must be an array.");
|
||||
return formatFatalError(Error::Type::JSONError, "Source contracts must be an array.");
|
||||
|
||||
for (auto const& contract: contracts)
|
||||
{
|
||||
if (!contract.isString())
|
||||
return formatFatalError("JSONError", "Every contract in settings.modelChecker.contracts must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "Every contract in settings.modelChecker.contracts must be a string.");
|
||||
if (contract.asString().empty())
|
||||
return formatFatalError("JSONError", "Contract name cannot be empty.");
|
||||
return formatFatalError(Error::Type::JSONError, "Contract name cannot be empty.");
|
||||
sourceContracts[source].insert(contract.asString());
|
||||
}
|
||||
|
||||
if (sourceContracts[source].empty())
|
||||
return formatFatalError("JSONError", "Source contracts must be a non-empty array.");
|
||||
return formatFatalError(Error::Type::JSONError, "Source contracts must be a non-empty array.");
|
||||
}
|
||||
ret.modelCheckerSettings.contracts = {std::move(sourceContracts)};
|
||||
}
|
||||
@ -980,17 +976,17 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
auto const& divModNoSlacks = modelCheckerSettings["divModNoSlacks"];
|
||||
if (!divModNoSlacks.isBool())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.divModNoSlacks must be a Boolean.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.divModNoSlacks must be a Boolean.");
|
||||
ret.modelCheckerSettings.divModNoSlacks = divModNoSlacks.asBool();
|
||||
}
|
||||
|
||||
if (modelCheckerSettings.isMember("engine"))
|
||||
{
|
||||
if (!modelCheckerSettings["engine"].isString())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.engine must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.engine must be a string.");
|
||||
std::optional<ModelCheckerEngine> engine = ModelCheckerEngine::fromString(modelCheckerSettings["engine"].asString());
|
||||
if (!engine)
|
||||
return formatFatalError("JSONError", "Invalid model checker engine requested.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid model checker engine requested.");
|
||||
ret.modelCheckerSettings.engine = *engine;
|
||||
}
|
||||
|
||||
@ -998,19 +994,19 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
auto const& invariantsArray = modelCheckerSettings["invariants"];
|
||||
if (!invariantsArray.isArray())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.invariants must be an array.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.invariants must be an array.");
|
||||
|
||||
ModelCheckerInvariants invariants;
|
||||
for (auto const& i: invariantsArray)
|
||||
{
|
||||
if (!i.isString())
|
||||
return formatFatalError("JSONError", "Every invariant type in settings.modelChecker.invariants must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "Every invariant type in settings.modelChecker.invariants must be a string.");
|
||||
if (!invariants.setFromString(i.asString()))
|
||||
return formatFatalError("JSONError", "Invalid model checker invariants requested.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid model checker invariants requested.");
|
||||
}
|
||||
|
||||
if (invariants.invariants.empty())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.invariants must be a non-empty array.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.invariants must be a non-empty array.");
|
||||
|
||||
ret.modelCheckerSettings.invariants = invariants;
|
||||
}
|
||||
@ -1019,7 +1015,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
auto const& showUnproved = modelCheckerSettings["showUnproved"];
|
||||
if (!showUnproved.isBool())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.showUnproved must be a Boolean value.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.showUnproved must be a Boolean value.");
|
||||
ret.modelCheckerSettings.showUnproved = showUnproved.asBool();
|
||||
}
|
||||
|
||||
@ -1027,15 +1023,15 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
auto const& solversArray = modelCheckerSettings["solvers"];
|
||||
if (!solversArray.isArray())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.solvers must be an array.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.solvers must be an array.");
|
||||
|
||||
smtutil::SMTSolverChoice solvers;
|
||||
for (auto const& s: solversArray)
|
||||
{
|
||||
if (!s.isString())
|
||||
return formatFatalError("JSONError", "Every target in settings.modelChecker.solvers must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "Every target in settings.modelChecker.solvers must be a string.");
|
||||
if (!solvers.setSolver(s.asString()))
|
||||
return formatFatalError("JSONError", "Invalid model checker solvers requested.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid model checker solvers requested.");
|
||||
}
|
||||
|
||||
ret.modelCheckerSettings.solvers = solvers;
|
||||
@ -1045,19 +1041,19 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
{
|
||||
auto const& targetsArray = modelCheckerSettings["targets"];
|
||||
if (!targetsArray.isArray())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.targets must be an array.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.targets must be an array.");
|
||||
|
||||
ModelCheckerTargets targets;
|
||||
for (auto const& t: targetsArray)
|
||||
{
|
||||
if (!t.isString())
|
||||
return formatFatalError("JSONError", "Every target in settings.modelChecker.targets must be a string.");
|
||||
return formatFatalError(Error::Type::JSONError, "Every target in settings.modelChecker.targets must be a string.");
|
||||
if (!targets.setFromString(t.asString()))
|
||||
return formatFatalError("JSONError", "Invalid model checker targets requested.");
|
||||
return formatFatalError(Error::Type::JSONError, "Invalid model checker targets requested.");
|
||||
}
|
||||
|
||||
if (targets.targets.empty())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.targets must be a non-empty array.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.targets must be a non-empty array.");
|
||||
|
||||
ret.modelCheckerSettings.targets = targets;
|
||||
}
|
||||
@ -1065,7 +1061,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
||||
if (modelCheckerSettings.isMember("timeout"))
|
||||
{
|
||||
if (!modelCheckerSettings["timeout"].isUInt())
|
||||
return formatFatalError("JSONError", "settings.modelChecker.timeout must be an unsigned integer.");
|
||||
return formatFatalError(Error::Type::JSONError, "settings.modelChecker.timeout must be an unsigned integer.");
|
||||
ret.modelCheckerSettings.timeout = modelCheckerSettings["timeout"].asUInt();
|
||||
}
|
||||
|
||||
@ -1116,8 +1112,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
errors.append(formatErrorWithException(
|
||||
compilerStack,
|
||||
*error,
|
||||
Error::errorSeverity(err.type()),
|
||||
err.typeName(),
|
||||
err.type(),
|
||||
"general",
|
||||
"",
|
||||
err.errorId()
|
||||
@ -1130,8 +1125,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
errors.append(formatErrorWithException(
|
||||
compilerStack,
|
||||
_error,
|
||||
Error::Severity::Error,
|
||||
_error.typeName(),
|
||||
_error.type(),
|
||||
"general",
|
||||
"Uncaught error: "
|
||||
));
|
||||
@ -1140,8 +1134,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
catch (FatalError const& _exception)
|
||||
{
|
||||
errors.append(formatError(
|
||||
Error::Severity::Error,
|
||||
"FatalError",
|
||||
Error::Type::FatalError,
|
||||
"general",
|
||||
"Uncaught fatal error: " + boost::diagnostic_information(_exception)
|
||||
));
|
||||
@ -1151,8 +1144,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
errors.append(formatErrorWithException(
|
||||
compilerStack,
|
||||
_exception,
|
||||
Error::Severity::Error,
|
||||
"CompilerError",
|
||||
Error::Type::CompilerError,
|
||||
"general",
|
||||
"Compiler error (" + _exception.lineInfo() + ")"
|
||||
));
|
||||
@ -1162,8 +1154,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
errors.append(formatErrorWithException(
|
||||
compilerStack,
|
||||
_exception,
|
||||
Error::Severity::Error,
|
||||
"InternalCompilerError",
|
||||
Error::Type::InternalCompilerError,
|
||||
"general",
|
||||
"Internal compiler error (" + _exception.lineInfo() + ")"
|
||||
));
|
||||
@ -1173,8 +1164,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
errors.append(formatErrorWithException(
|
||||
compilerStack,
|
||||
_exception,
|
||||
Error::Severity::Error,
|
||||
"UnimplementedFeatureError",
|
||||
Error::Type::UnimplementedFeatureError,
|
||||
"general",
|
||||
"Unimplemented feature (" + _exception.lineInfo() + ")"
|
||||
));
|
||||
@ -1184,8 +1174,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
errors.append(formatErrorWithException(
|
||||
compilerStack,
|
||||
_exception,
|
||||
Error::Severity::Error,
|
||||
"YulException",
|
||||
Error::Type::YulException,
|
||||
"general",
|
||||
"Yul exception"
|
||||
));
|
||||
@ -1195,8 +1184,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
errors.append(formatErrorWithException(
|
||||
compilerStack,
|
||||
_exception,
|
||||
Error::Severity::Error,
|
||||
"SMTLogicException",
|
||||
Error::Type::SMTLogicException,
|
||||
"general",
|
||||
"SMT logic exception"
|
||||
));
|
||||
@ -1204,8 +1192,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
catch (util::Exception const& _exception)
|
||||
{
|
||||
errors.append(formatError(
|
||||
Error::Severity::Error,
|
||||
"Exception",
|
||||
Error::Type::Exception,
|
||||
"general",
|
||||
"Exception during compilation: " + boost::diagnostic_information(_exception)
|
||||
));
|
||||
@ -1213,8 +1200,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
catch (std::exception const& _exception)
|
||||
{
|
||||
errors.append(formatError(
|
||||
Error::Severity::Error,
|
||||
"Exception",
|
||||
Error::Type::Exception,
|
||||
"general",
|
||||
"Unknown exception during compilation: " + boost::diagnostic_information(_exception)
|
||||
));
|
||||
@ -1222,8 +1208,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
catch (...)
|
||||
{
|
||||
errors.append(formatError(
|
||||
Error::Severity::Error,
|
||||
"Exception",
|
||||
Error::Type::Exception,
|
||||
"general",
|
||||
"Unknown exception during compilation: " + boost::current_exception_diagnostic_information()
|
||||
));
|
||||
@ -1240,7 +1225,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
||||
((binariesRequested && !compilationSuccess) || !analysisPerformed) &&
|
||||
(errors.empty() && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed)
|
||||
)
|
||||
return formatFatalError("InternalCompilerError", "No error reported, but compilation failed.");
|
||||
return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed.");
|
||||
|
||||
Json::Value output = Json::objectValue;
|
||||
|
||||
@ -1376,8 +1361,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
if (_inputsAndSettings.sources.size() != 1)
|
||||
{
|
||||
output["errors"].append(formatError(
|
||||
Error::Severity::Error,
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"general",
|
||||
"Yul mode only supports exactly one input file."
|
||||
));
|
||||
@ -1386,8 +1370,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
if (!_inputsAndSettings.smtLib2Responses.empty())
|
||||
{
|
||||
output["errors"].append(formatError(
|
||||
Error::Severity::Error,
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"general",
|
||||
"Yul mode does not support smtlib2responses."
|
||||
));
|
||||
@ -1396,8 +1379,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
if (!_inputsAndSettings.remappings.empty())
|
||||
{
|
||||
output["errors"].append(formatError(
|
||||
Error::Severity::Error,
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"general",
|
||||
"Field \"settings.remappings\" cannot be used for Yul."
|
||||
));
|
||||
@ -1406,8 +1388,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
if (_inputsAndSettings.revertStrings != RevertStrings::Default)
|
||||
{
|
||||
output["errors"].append(formatError(
|
||||
Error::Severity::Error,
|
||||
"JSONError",
|
||||
Error::Type::JSONError,
|
||||
"general",
|
||||
"Field \"settings.debug.revertStrings\" cannot be used for Yul."
|
||||
));
|
||||
@ -1429,8 +1410,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty())
|
||||
{
|
||||
output["errors"].append(formatError(
|
||||
Error::Severity::Error,
|
||||
"InternalCompilerError",
|
||||
Error::Type::InternalCompilerError,
|
||||
"general",
|
||||
"No error reported, but compilation failed."
|
||||
));
|
||||
@ -1446,8 +1426,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
|
||||
output["errors"].append(formatErrorWithException(
|
||||
stack,
|
||||
*error,
|
||||
Error::errorSeverity(err->type()),
|
||||
err->typeName(),
|
||||
err->type(),
|
||||
"general",
|
||||
""
|
||||
));
|
||||
@ -1523,23 +1502,23 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept
|
||||
else if (settings.language == "Yul")
|
||||
return compileYul(std::move(settings));
|
||||
else
|
||||
return formatFatalError("JSONError", "Only \"Solidity\" or \"Yul\" is supported as a language.");
|
||||
return formatFatalError(Error::Type::JSONError, "Only \"Solidity\" or \"Yul\" is supported as a language.");
|
||||
}
|
||||
catch (Json::LogicError const& _exception)
|
||||
{
|
||||
return formatFatalError("InternalCompilerError", string("JSON logic exception: ") + _exception.what());
|
||||
return formatFatalError(Error::Type::InternalCompilerError, string("JSON logic exception: ") + _exception.what());
|
||||
}
|
||||
catch (Json::RuntimeError const& _exception)
|
||||
{
|
||||
return formatFatalError("InternalCompilerError", string("JSON runtime exception: ") + _exception.what());
|
||||
return formatFatalError(Error::Type::InternalCompilerError, string("JSON runtime exception: ") + _exception.what());
|
||||
}
|
||||
catch (util::Exception const& _exception)
|
||||
{
|
||||
return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compile: " + boost::diagnostic_information(_exception));
|
||||
return formatFatalError(Error::Type::InternalCompilerError, "Internal exception in StandardCompiler::compile: " + boost::diagnostic_information(_exception));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compile: " + boost::current_exception_diagnostic_information());
|
||||
return formatFatalError(Error::Type::InternalCompilerError, "Internal exception in StandardCompiler::compile: " + boost::current_exception_diagnostic_information());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1550,7 +1529,7 @@ string StandardCompiler::compile(string const& _input) noexcept
|
||||
try
|
||||
{
|
||||
if (!util::jsonParseStrict(_input, input, &errors))
|
||||
return util::jsonPrint(formatFatalError("JSONError", errors), m_jsonPrintingFormat);
|
||||
return util::jsonPrint(formatFatalError(Error::Type::JSONError, errors), m_jsonPrintingFormat);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -286,7 +286,7 @@ void LanguageServer::compileAndUpdateDiagnostics()
|
||||
jsonDiag["source"] = "solc";
|
||||
jsonDiag["severity"] = toDiagnosticSeverity(error->type());
|
||||
jsonDiag["code"] = Json::UInt64{error->errorId().error};
|
||||
string message = error->typeName() + ":";
|
||||
string message = Error::formatErrorType(error->type()) + ":";
|
||||
if (string const* comment = error->comment())
|
||||
message += " " + *comment;
|
||||
jsonDiag["message"] = std::move(message);
|
||||
|
@ -765,7 +765,10 @@ void CommandLineInterface::compile()
|
||||
catch (CompilerError const& _exception)
|
||||
{
|
||||
m_hasOutput = true;
|
||||
formatter.printExceptionInformation(_exception, "Compiler error");
|
||||
formatter.printExceptionInformation(
|
||||
_exception,
|
||||
Error::errorSeverity(Error::Type::CompilerError)
|
||||
);
|
||||
solThrow(CommandLineExecutionError, "");
|
||||
}
|
||||
catch (Error const& _error)
|
||||
@ -778,7 +781,7 @@ void CommandLineInterface::compile()
|
||||
else
|
||||
{
|
||||
m_hasOutput = true;
|
||||
formatter.printExceptionInformation(_error, _error.typeName());
|
||||
formatter.printExceptionInformation(_error, Error::errorSeverity(_error.type()));
|
||||
solThrow(CommandLineExecutionError, "");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,2 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity *;
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources": {
|
||||
"url_not_found.sol": {
|
||||
"urls": [
|
||||
"standard_urls_existing_and_missing/non-existent-contract-1.sol",
|
||||
"standard_urls_existing_and_missing/contract.sol",
|
||||
"standard_urls_existing_and_missing/non-existent-contract-2.sol"
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {"outputSelection": {"*": { "*": ["metadata", "evm.bytecode"]}}}
|
||||
}
|
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Cannot import url (\"standard_urls_existing_and_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".","message":"Cannot import url (\"standard_urls_existing_and_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".","severity":"warning","type":"Warning"}],"sources":{"url_not_found.sol":{"id":0}}}
|
2
test/cmdlineTests/standard_urls_missing/contract.sol
Normal file
2
test/cmdlineTests/standard_urls_missing/contract.sol
Normal file
@ -0,0 +1,2 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity *;
|
13
test/cmdlineTests/standard_urls_missing/input.json
Normal file
13
test/cmdlineTests/standard_urls_missing/input.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources": {
|
||||
"url_not_found.sol": {
|
||||
"urls": [
|
||||
"standard_urls_missing/non-existent-contract-1.sol",
|
||||
"standard_urls_missing/non-existent-contract.sol",
|
||||
"standard_urls_missing/non-existent-contract-2.sol"
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {"outputSelection": {"*": { "*": ["metadata", "evm.bytecode"]}}}
|
||||
}
|
1
test/cmdlineTests/standard_urls_missing/output.json
Normal file
1
test/cmdlineTests/standard_urls_missing/output.json
Normal file
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Cannot import url (\"standard_urls_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".","message":"Cannot import url (\"standard_urls_missing/non-existent-contract-1.sol\"): File not found. Searched the following locations: \"\".","severity":"error","type":"IOError"},{"component":"general","formattedMessage":"Cannot import url (\"standard_urls_missing/non-existent-contract.sol\"): File not found. Searched the following locations: \"\".","message":"Cannot import url (\"standard_urls_missing/non-existent-contract.sol\"): File not found. Searched the following locations: \"\".","severity":"error","type":"IOError"},{"component":"general","formattedMessage":"Cannot import url (\"standard_urls_missing/non-existent-contract-2.sol\"): File not found. Searched the following locations: \"\".","message":"Cannot import url (\"standard_urls_missing/non-existent-contract-2.sol\"): File not found. Searched the following locations: \"\".","severity":"error","type":"IOError"}],"sources":{}}
|
@ -71,7 +71,7 @@ string solidity::frontend::test::searchErrors(ErrorList const& _errors, vector<p
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
return "Unexpected error: " + error->typeName() + ": " + msg;
|
||||
return "Unexpected error: " + Error::formatErrorType(error->type()) + ": " + msg;
|
||||
}
|
||||
if (!expectations.empty())
|
||||
{
|
||||
|
@ -145,7 +145,7 @@ void SyntaxTest::filterObtainedErrors()
|
||||
}
|
||||
}
|
||||
m_errorList.emplace_back(SyntaxTestError{
|
||||
currentError->typeName(),
|
||||
Error::formatErrorType(currentError->type()),
|
||||
currentError->errorId(),
|
||||
errorMessage(*currentError),
|
||||
sourceName,
|
||||
|
@ -61,7 +61,7 @@ void SyntaxTest::parseAndAnalyze()
|
||||
}
|
||||
|
||||
m_errorList.emplace_back(SyntaxTestError{
|
||||
error->typeName(),
|
||||
Error::formatErrorType(error->type()),
|
||||
error->errorId(),
|
||||
errorMessage(*error),
|
||||
name,
|
||||
|
@ -79,10 +79,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
|
||||
SourceReferenceFormatter formatter(std::cout, stack, false, false);
|
||||
|
||||
for (auto const& error: stack.errors())
|
||||
formatter.printExceptionInformation(
|
||||
*error,
|
||||
(error->type() == Error::Type::Warning) ? "Warning" : "Error"
|
||||
);
|
||||
formatter.printExceptionInformation(*error, Error::errorSeverity(error->type()));
|
||||
yulAssert(false, "Proto fuzzer generated malformed program");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user