diff --git a/liblangutil/Exceptions.cpp b/liblangutil/Exceptions.cpp index 2595c7755..92fe2589a 100644 --- a/liblangutil/Exceptions.cpp +++ b/liblangutil/Exceptions.cpp @@ -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(*this); } - -optional 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; -} diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index fb6f23cf1..fc7286ed1 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -31,11 +31,13 @@ #include #include #include +#include #include #include #include #include +#include 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 _typeOrSeverity) + { + if (std::holds_alternative(_typeOrSeverity)) + return errorSeverity(std::get(_typeOrSeverity)); + return std::get(_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 _typeOrSeverity) + { + if (std::holds_alternative(_typeOrSeverity)) + return formatErrorType(std::get(_typeOrSeverity)); + return formatErrorSeverity(std::get(_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 severityFromString(std::string _input); - private: ErrorId m_errorId; Type m_type; - std::string m_typeName; }; } diff --git a/liblangutil/SourceReferenceExtractor.cpp b/liblangutil/SourceReferenceExtractor.cpp index 373ad6b18..01f22a1f7 100644 --- a/liblangutil/SourceReferenceExtractor.cpp +++ b/liblangutil/SourceReferenceExtractor.cpp @@ -22,6 +22,7 @@ #include #include +#include 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 _typeOrSeverity ) { SourceLocation const* location = boost::get_error_info(_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 _typeOrSeverity ) { - string severity = Error::formatErrorSeverity(Error::errorSeverity(_error.type())); - Message message = extract(_charStreamProvider, _error, severity); + Message message = extract(_charStreamProvider, static_cast(_error), _typeOrSeverity); message.errorId = _error.errorId(); return message; } diff --git a/liblangutil/SourceReferenceExtractor.h b/liblangutil/SourceReferenceExtractor.h index 3b418fcfa..3f7751f0b 100644 --- a/liblangutil/SourceReferenceExtractor.h +++ b/liblangutil/SourceReferenceExtractor.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace solidity::langutil { @@ -55,12 +56,21 @@ namespace SourceReferenceExtractor struct Message { SourceReference primary; - std::string severity; // "Error", "Warning", "Info", ... + std::variant _typeOrSeverity; std::vector secondary; std::optional errorId; }; - Message extract(CharStreamProvider const& _charStreamProvider, util::Exception const& _exception, std::string _severity); + Message extract( + CharStreamProvider const& _charStreamProvider, + util::Exception const& _exception, + std::variant _typeOrSeverity + ); + Message extract( + CharStreamProvider const& _charStreamProvider, + Error const& _error, + std::variant _typeOrSeverity + ); Message extract(CharStreamProvider const& _charStreamProvider, Error const& _error); SourceReference extract(CharStreamProvider const& _charStreamProvider, SourceLocation const* _location, std::string message = ""); } diff --git a/liblangutil/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp index a38c5e617..4765b9fb2 100644 --- a/liblangutil/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -26,6 +26,7 @@ #include #include #include +#include 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 _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 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); } diff --git a/liblangutil/SourceReferenceFormatter.h b/liblangutil/SourceReferenceFormatter.h index e18400b60..def216efa 100644 --- a/liblangutil/SourceReferenceFormatter.h +++ b/liblangutil/SourceReferenceFormatter.h @@ -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 _severity) const; + util::AnsiColorized errorColored(langutil::Error::Severity _severity) const; util::AnsiColorized messageColored() const; util::AnsiColorized secondaryColored() const; util::AnsiColorized highlightColored() const; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 0af55df16..551bd6af7 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -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 = 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 checkKeys(Json::Value const& _input, set 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 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 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 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 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 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 keys{"useLiteralContent", "bytecodeHash"}; return checkKeys(_input, keys, "settings.metadata"); @@ -524,7 +523,7 @@ std::optional checkMetadataKeys(Json::Value const& _input) std::optional 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 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 checkOutputSelection(Json::Value const& _outputSelect if (!contractVal.isArray()) return formatFatalError( - "JSONError", + Error::Type::JSONError, "\"settings.outputSelection." + sourceName + "." + @@ -553,7 +552,7 @@ std::optional 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 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 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 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 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: 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: 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: 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 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: { /// 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: 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: } 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: 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: 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 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: 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 = 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: 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 components; for (Json::Value const& arrayValue: settings["debug"]["debugInfo"]) @@ -836,11 +832,11 @@ std::variant 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: } 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: 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: catch (util::BadHexCharacter const&) { return formatFatalError( - "JSONError", + Error::Type::JSONError, "Invalid library address (\"" + address + "\") supplied." ); } @@ -936,7 +932,7 @@ std::variant 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: { 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> 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: { 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 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: { 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: { 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: { 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: { 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: 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 (...) { diff --git a/libsolidity/lsp/LanguageServer.cpp b/libsolidity/lsp/LanguageServer.cpp index ce68dbef3..1a1f5faf0 100644 --- a/libsolidity/lsp/LanguageServer.cpp +++ b/libsolidity/lsp/LanguageServer.cpp @@ -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); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index e215405a1..ccaa8df94 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -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, ""); } } diff --git a/test/cmdlineTests/standard_urls_existing_and_missing/contract.sol b/test/cmdlineTests/standard_urls_existing_and_missing/contract.sol new file mode 100644 index 000000000..a32f63f78 --- /dev/null +++ b/test/cmdlineTests/standard_urls_existing_and_missing/contract.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; diff --git a/test/cmdlineTests/standard_urls_existing_and_missing/input.json b/test/cmdlineTests/standard_urls_existing_and_missing/input.json new file mode 100644 index 000000000..686e8128e --- /dev/null +++ b/test/cmdlineTests/standard_urls_existing_and_missing/input.json @@ -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"]}}} +} diff --git a/test/cmdlineTests/standard_urls_existing_and_missing/output.json b/test/cmdlineTests/standard_urls_existing_and_missing/output.json new file mode 100644 index 000000000..8cb0cc4c7 --- /dev/null +++ b/test/cmdlineTests/standard_urls_existing_and_missing/output.json @@ -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}}} diff --git a/test/cmdlineTests/standard_urls_missing/contract.sol b/test/cmdlineTests/standard_urls_missing/contract.sol new file mode 100644 index 000000000..a32f63f78 --- /dev/null +++ b/test/cmdlineTests/standard_urls_missing/contract.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity *; diff --git a/test/cmdlineTests/standard_urls_missing/input.json b/test/cmdlineTests/standard_urls_missing/input.json new file mode 100644 index 000000000..fecc50eb0 --- /dev/null +++ b/test/cmdlineTests/standard_urls_missing/input.json @@ -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"]}}} +} diff --git a/test/cmdlineTests/standard_urls_missing/output.json b/test/cmdlineTests/standard_urls_missing/output.json new file mode 100644 index 000000000..2bead4831 --- /dev/null +++ b/test/cmdlineTests/standard_urls_missing/output.json @@ -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":{}} diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp index 418d7cc99..8a8b2166c 100644 --- a/test/libsolidity/ErrorCheck.cpp +++ b/test/libsolidity/ErrorCheck.cpp @@ -71,7 +71,7 @@ string solidity::frontend::test::searchErrors(ErrorList const& _errors, vector

typeName() + ": " + msg; + return "Unexpected error: " + Error::formatErrorType(error->type()) + ": " + msg; } if (!expectations.empty()) { diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index d3e512450..ee3c4b4b0 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -145,7 +145,7 @@ void SyntaxTest::filterObtainedErrors() } } m_errorList.emplace_back(SyntaxTestError{ - currentError->typeName(), + Error::formatErrorType(currentError->type()), currentError->errorId(), errorMessage(*currentError), sourceName, diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 8ab5bb953..cea1d5745 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -61,7 +61,7 @@ void SyntaxTest::parseAndAnalyze() } m_errorList.emplace_back(SyntaxTestError{ - error->typeName(), + Error::formatErrorType(error->type()), error->errorId(), errorMessage(*error), name, diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index c3ad9c9f3..2335bfbf5 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -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"); }