Add new info severity

This commit is contained in:
Leo Alt 2021-06-30 14:48:45 +02:00
parent 49cde9d47b
commit e72fa7fc10
38 changed files with 191 additions and 97 deletions

View File

@ -389,6 +389,10 @@ code.
Always use the latest version of the compiler to be notified about all recently Always use the latest version of the compiler to be notified about all recently
introduced warnings. introduced warnings.
Messages of type ``info`` issued by the compiler are not dangerous, and simply
represent extra suggestions and optional information that the compiler thinks
might be useful to the user.
Restrict the Amount of Ether Restrict the Amount of Ether
============================ ============================

View File

@ -437,7 +437,7 @@ Output Description
.. code-block:: javascript .. code-block:: javascript
{ {
// Optional: not present if no errors/warnings were encountered // Optional: not present if no errors/warnings/infos were encountered
"errors": [ "errors": [
{ {
// Optional: Location within the source file. // Optional: Location within the source file.
@ -460,7 +460,7 @@ Output Description
"type": "TypeError", "type": "TypeError",
// Mandatory: Component where the error originated, such as "general", "ewasm", etc. // Mandatory: Component where the error originated, such as "general", "ewasm", etc.
"component": "general", "component": "general",
// Mandatory ("error" or "warning") // Mandatory ("error", "warning" or "info", but please note that this may be extended in the future)
"severity": "error", "severity": "error",
// Optional: unique code for the cause of the error // Optional: unique code for the cause of the error
"errorCode": "3141", "errorCode": "3141",
@ -604,6 +604,7 @@ Error Types
11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue. 11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue.
12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue. 12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue.
13. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible. 13. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible.
14. ``Info``: Information that the compiler thinks the user might find useful, but is not dangerous and does not necessarily need to be addressed.
.. _compiler-tools: .. _compiler-tools:

View File

@ -94,6 +94,16 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
if (m_warningCount >= c_maxWarningsAllowed) if (m_warningCount >= c_maxWarningsAllowed)
return true; return true;
} }
else if (_type == Error::Type::Info)
{
m_infoCount++;
if (m_infoCount == c_maxInfosAllowed)
m_errorList.push_back(make_shared<Error>(2833_error, Error::Type::Info, "There are more than 256 infos. Ignoring the rest."));
if (m_infoCount >= c_maxInfosAllowed)
return true;
}
else else
{ {
m_errorCount++; m_errorCount++;
@ -242,3 +252,12 @@ void ErrorReporter::docstringParsingError(ErrorId _error, SourceLocation const&
_description _description
); );
} }
void ErrorReporter::info(
ErrorId _error,
SourceLocation const& _location,
string const& _description
)
{
error(_error, Error::Type::Info, _location, _description);
}

View File

@ -63,6 +63,8 @@ public:
SecondarySourceLocation const& _secondaryLocation SecondarySourceLocation const& _secondaryLocation
); );
void info(ErrorId _error, SourceLocation const& _location, std::string const& _description);
void error( void error(
ErrorId _error, ErrorId _error,
Error::Type _type, Error::Type _type,
@ -118,13 +120,13 @@ public:
void clear(); void clear();
/// @returns true iff there is any error (ignores warnings). /// @returns true iff there is any error (ignores warnings and infos).
bool hasErrors() const bool hasErrors() const
{ {
return m_errorCount > 0; return m_errorCount > 0;
} }
/// @returns the number of errors (ignores warnings). /// @returns the number of errors (ignores warnings and infos).
unsigned errorCount() const unsigned errorCount() const
{ {
return m_errorCount; return m_errorCount;
@ -183,9 +185,11 @@ private:
unsigned m_errorCount = 0; unsigned m_errorCount = 0;
unsigned m_warningCount = 0; unsigned m_warningCount = 0;
unsigned m_infoCount = 0;
unsigned const c_maxWarningsAllowed = 256; unsigned const c_maxWarningsAllowed = 256;
unsigned const c_maxErrorsAllowed = 256; unsigned const c_maxErrorsAllowed = 256;
unsigned const c_maxInfosAllowed = 256;
}; };
} }

View File

@ -47,6 +47,9 @@ Error::Error(
case Type::DocstringParsingError: case Type::DocstringParsingError:
m_typeName = "DocstringParsingError"; m_typeName = "DocstringParsingError";
break; break;
case Type::Info:
m_typeName = "Info";
break;
case Type::ParserError: case Type::ParserError:
m_typeName = "ParserError"; m_typeName = "ParserError";
break; break;

View File

@ -120,7 +120,15 @@ public:
ParserError, ParserError,
TypeError, TypeError,
SyntaxError, SyntaxError,
Warning Warning,
Info
};
enum class Severity
{
Error,
Warning,
Info
}; };
Error( Error(
@ -139,21 +147,63 @@ public:
static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type) static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type)
{ {
for (auto e: _list) for (auto e: _list)
{
if (e->type() == _type) if (e->type() == _type)
return e.get(); return e.get();
}
return nullptr; return nullptr;
} }
static bool containsOnlyWarnings(ErrorList const& _list)
static Severity errorSeverity(Type _type)
{
if (_type == Type::Info)
return Severity::Info;
if (_type == Type::Warning)
return Severity::Warning;
return Severity::Error;
}
static bool isError(Severity _severity)
{
return _severity == Severity::Error;
}
static bool isError(Type _type)
{
return isError(errorSeverity(_type));
}
static bool containsErrors(ErrorList const& _list)
{ {
for (auto e: _list) for (auto e: _list)
{ if (isError(e->type()))
if (e->type() != Type::Warning) return true;
return false; return false;
}
return true;
} }
static std::string formatErrorSeverity(Severity _severity)
{
if (_severity == Severity::Info)
return "Info";
if (_severity == Severity::Warning)
return "Warning";
solAssert(isError(_severity), "");
return "Error";
}
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, "");
}
private: private:
ErrorId m_errorId; ErrorId m_errorId;
Type m_type; Type m_type;

View File

@ -104,7 +104,7 @@ protected:
void fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description); void fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description);
std::shared_ptr<Scanner> m_scanner; std::shared_ptr<Scanner> m_scanner;
/// The reference to the list of errors and warning to add errors/warnings during parsing /// The reference to the list of errors, warnings and infos to add errors/warnings/infos during parsing
ErrorReporter& m_errorReporter; ErrorReporter& m_errorReporter;
/// Current recursion depth during parsing. /// Current recursion depth during parsing.
size_t m_recursionDepth = 0; size_t m_recursionDepth = 0;

View File

@ -30,7 +30,7 @@ using namespace solidity::langutil;
SourceReferenceExtractor::Message SourceReferenceExtractor::extract( SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
CharStreamProvider const& _charStreamProvider, CharStreamProvider const& _charStreamProvider,
util::Exception const& _exception, util::Exception const& _exception,
string _category string _severity
) )
{ {
SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception); SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
@ -44,7 +44,7 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
for (auto const& info: secondaryLocation->infos) for (auto const& info: secondaryLocation->infos)
secondary.emplace_back(extract(_charStreamProvider, &info.second, info.first)); secondary.emplace_back(extract(_charStreamProvider, &info.second, info.first));
return Message{std::move(primary), _category, std::move(secondary), nullopt}; return Message{std::move(primary), _severity, std::move(secondary), nullopt};
} }
SourceReferenceExtractor::Message SourceReferenceExtractor::extract( SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
@ -52,8 +52,8 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(
Error const& _error Error const& _error
) )
{ {
string category = (_error.type() == Error::Type::Warning) ? "Warning" : "Error"; string severity = Error::formatErrorSeverity(Error::errorSeverity(_error.type()));
Message message = extract(_charStreamProvider, _error, category); Message message = extract(_charStreamProvider, _error, severity);
message.errorId = _error.errorId(); message.errorId = _error.errorId();
return message; return message;
} }

View File

@ -41,7 +41,7 @@ struct LineColumn
struct SourceReference struct SourceReference
{ {
std::string message; ///< A message that relates to this source reference (such as a warning or an error message). std::string message; ///< A message that relates to this source reference (such as a warning, info or an error message).
std::string sourceName; ///< Underlying source name (for example the filename). std::string sourceName; ///< Underlying source name (for example the filename).
LineColumn position; ///< Actual (error) position this source reference is surrounding. LineColumn position; ///< Actual (error) position this source reference is surrounding.
bool multiline = {false}; ///< Indicates whether the actual SourceReference is truncated to one line. bool multiline = {false}; ///< Indicates whether the actual SourceReference is truncated to one line.
@ -64,12 +64,12 @@ namespace SourceReferenceExtractor
struct Message struct Message
{ {
SourceReference primary; SourceReference primary;
std::string category; // "Error", "Warning", ... std::string severity; // "Error", "Warning", "Info", ...
std::vector<SourceReference> secondary; std::vector<SourceReference> secondary;
std::optional<ErrorId> errorId; std::optional<ErrorId> errorId;
}; };
Message extract(CharStreamProvider const& _charStreamProvider, util::Exception const& _exception, std::string _category); Message extract(CharStreamProvider const& _charStreamProvider, util::Exception const& _exception, std::string _severity);
Message extract(CharStreamProvider const& _charStreamProvider, Error const& _error); Message extract(CharStreamProvider const& _charStreamProvider, Error const& _error);
SourceReference extract(CharStreamProvider const& _charStreamProvider, SourceLocation const* _location, std::string message = ""); SourceReference extract(CharStreamProvider const& _charStreamProvider, SourceLocation const* _location, std::string message = "");
} }

View File

@ -164,7 +164,7 @@ void SourceReferenceFormatter::printSourceLocation(SourceReference const& _ref)
void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg) void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg)
{ {
// exception header line // exception header line
errorColored() << _msg.category; errorColored() << _msg.severity;
if (m_withErrorIds && _msg.errorId.has_value()) if (m_withErrorIds && _msg.errorId.has_value())
errorColored() << " (" << _msg.errorId.value().error << ")"; errorColored() << " (" << _msg.errorId.value().error << ")";
messageColored() << ": " << _msg.primary.message << '\n'; messageColored() << ": " << _msg.primary.message << '\n';
@ -181,9 +181,9 @@ void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtracto
m_stream << '\n'; m_stream << '\n';
} }
void SourceReferenceFormatter::printExceptionInformation(util::Exception const& _exception, std::string const& _category) void SourceReferenceFormatter::printExceptionInformation(util::Exception const& _exception, std::string const& _severity)
{ {
printExceptionInformation(SourceReferenceExtractor::extract(m_charStreamProvider, _exception, _category)); printExceptionInformation(SourceReferenceExtractor::extract(m_charStreamProvider, _exception, _severity));
} }
void SourceReferenceFormatter::printErrorInformation(ErrorList const& _errors) void SourceReferenceFormatter::printErrorInformation(ErrorList const& _errors)

View File

@ -52,7 +52,7 @@ public:
/// Prints source location if it is given. /// Prints source location if it is given.
void printSourceLocation(SourceReference const& _ref); void printSourceLocation(SourceReference const& _ref);
void printExceptionInformation(SourceReferenceExtractor::Message const& _msg); void printExceptionInformation(SourceReferenceExtractor::Message const& _msg);
void printExceptionInformation(util::Exception const& _exception, std::string const& _category); void printExceptionInformation(util::Exception const& _exception, std::string const& _severity);
void printErrorInformation(langutil::ErrorList const& _errors); void printErrorInformation(langutil::ErrorList const& _errors);
void printErrorInformation(Error const& _error); void printErrorInformation(Error const& _error);
@ -77,7 +77,7 @@ public:
{ {
return formatExceptionInformation( return formatExceptionInformation(
_error, _error,
(_error.type() == Error::Type::Warning) ? "Warning" : "Error", Error::formatErrorSeverity(Error::errorSeverity(_error.type())),
_charStreamProvider _charStreamProvider
); );
} }

View File

@ -71,7 +71,7 @@ bool ContractLevelChecker::check(SourceUnit const& _sourceUnit)
findDuplicateDefinitions( findDuplicateDefinitions(
filterDeclarations<EventDefinition>(*_sourceUnit.annotation().exportedSymbols) filterDeclarations<EventDefinition>(*_sourceUnit.annotation().exportedSymbols)
); );
if (!Error::containsOnlyWarnings(m_errorReporter.errors())) if (Error::containsErrors(m_errorReporter.errors()))
noErrors = false; noErrors = false;
for (ASTPointer<ASTNode> const& node: _sourceUnit.nodes()) for (ASTPointer<ASTNode> const& node: _sourceUnit.nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
@ -97,7 +97,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract)
checkPayableFallbackWithoutReceive(_contract); checkPayableFallbackWithoutReceive(_contract);
checkStorageSize(_contract); checkStorageSize(_contract);
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }
void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _contract) void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _contract)

View File

@ -36,7 +36,7 @@ bool ControlFlowAnalyzer::run()
for (auto& [pair, flow]: m_cfg.allFunctionFlows()) for (auto& [pair, flow]: m_cfg.allFunctionFlows())
analyze(*pair.function, pair.contract, *flow); analyze(*pair.function, pair.contract, *flow);
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }
void ControlFlowAnalyzer::analyze(FunctionDefinition const& _function, ContractDefinition const* _contract, FunctionFlow const& _flow) void ControlFlowAnalyzer::analyze(FunctionDefinition const& _function, ContractDefinition const* _contract, FunctionFlow const& _flow)

View File

@ -27,7 +27,7 @@ using namespace solidity::frontend;
bool CFG::constructFlow(ASTNode const& _astRoot) bool CFG::constructFlow(ASTNode const& _astRoot)
{ {
_astRoot.accept(*this); _astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }

View File

@ -36,14 +36,14 @@ using namespace solidity::frontend;
bool PostTypeChecker::check(ASTNode const& _astRoot) bool PostTypeChecker::check(ASTNode const& _astRoot)
{ {
_astRoot.accept(*this); _astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }
bool PostTypeChecker::finalize() bool PostTypeChecker::finalize()
{ {
for (auto& checker: m_checkers) for (auto& checker: m_checkers)
checker->finalize(); checker->finalize();
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }
bool PostTypeChecker::visit(ContractDefinition const& _contractDefinition) bool PostTypeChecker::visit(ContractDefinition const& _contractDefinition)

View File

@ -68,5 +68,5 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract)
errorHashes[hash][signature] = error->location(); errorHashes[hash][signature] = error->location();
} }
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }

View File

@ -86,7 +86,7 @@ StaticAnalyzer::~StaticAnalyzer()
bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit) bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit)
{ {
_sourceUnit.accept(*this); _sourceUnit.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }
bool StaticAnalyzer::visit(ContractDefinition const& _contract) bool StaticAnalyzer::visit(ContractDefinition const& _contract)

View File

@ -41,7 +41,7 @@ using namespace solidity::util;
bool SyntaxChecker::checkSyntax(ASTNode const& _astRoot) bool SyntaxChecker::checkSyntax(ASTNode const& _astRoot)
{ {
_astRoot.accept(*this); _astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }
bool SyntaxChecker::visit(SourceUnit const& _sourceUnit) bool SyntaxChecker::visit(SourceUnit const& _sourceUnit)

View File

@ -73,7 +73,7 @@ bool TypeChecker::checkTypeRequirements(SourceUnit const& _source)
m_currentSourceUnit = &_source; m_currentSourceUnit = &_source;
_source.accept(*this); _source.accept(*this);
m_currentSourceUnit = nullptr; m_currentSourceUnit = nullptr;
return Error::containsOnlyWarnings(m_errorReporter.errors()); return !Error::containsErrors(m_errorReporter.errors());
} }
Type const* TypeChecker::type(Expression const& _expression) const Type const* TypeChecker::type(Expression const& _expression) const

View File

@ -338,7 +338,7 @@ bool CompilerStack::parse()
Source& source = m_sources[path]; Source& source = m_sources[path];
source.ast = parser.parse(*source.charStream); source.ast = parser.parse(*source.charStream);
if (!source.ast) if (!source.ast)
solAssert(!Error::containsOnlyWarnings(m_errorReporter.errors()), "Parser returned null but did not report error."); solAssert(Error::containsErrors(m_errorReporter.errors()), "Parser returned null but did not report error.");
else else
{ {
source.ast->annotation().path = path; source.ast->annotation().path = path;
@ -357,7 +357,7 @@ bool CompilerStack::parse()
m_stackState = Parsed; m_stackState = Parsed;
else else
m_stackState = ParsedAndImported; m_stackState = ParsedAndImported;
if (!Error::containsOnlyWarnings(m_errorReporter.errors())) if (Error::containsErrors(m_errorReporter.errors()))
m_hasError = true; m_hasError = true;
storeContractDefinitions(); storeContractDefinitions();

View File

@ -50,7 +50,7 @@ namespace
{ {
Json::Value formatError( Json::Value formatError(
bool _warning, Error::Severity _severity,
string const& _type, string const& _type,
string const& _component, string const& _component,
string const& _message, string const& _message,
@ -62,7 +62,7 @@ Json::Value formatError(
Json::Value error = Json::objectValue; Json::Value error = Json::objectValue;
error["type"] = _type; error["type"] = _type;
error["component"] = _component; error["component"] = _component;
error["severity"] = _warning ? "warning" : "error"; error["severity"] = Error::formatErrorSeverityLowercase(_severity);
error["message"] = _message; error["message"] = _message;
error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message; error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message;
if (_sourceLocation.isObject()) if (_sourceLocation.isObject())
@ -76,7 +76,7 @@ Json::Value formatFatalError(string const& _type, string const& _message)
{ {
Json::Value output = Json::objectValue; Json::Value output = Json::objectValue;
output["errors"] = Json::arrayValue; output["errors"] = Json::arrayValue;
output["errors"].append(formatError(false, _type, "general", _message)); output["errors"].append(formatError(Error::Severity::Error, _type, "general", _message));
return output; return output;
} }
@ -111,7 +111,7 @@ Json::Value formatSecondarySourceLocation(SecondarySourceLocation const* _second
Json::Value formatErrorWithException( Json::Value formatErrorWithException(
CharStreamProvider const& _charStreamProvider, CharStreamProvider const& _charStreamProvider,
util::Exception const& _exception, util::Exception const& _exception,
bool const& _warning, Error::Severity _severity,
string const& _type, string const& _type,
string const& _component, string const& _component,
string const& _message, string const& _message,
@ -132,7 +132,7 @@ Json::Value formatErrorWithException(
message = _message; message = _message;
Json::Value error = formatError( Json::Value error = formatError(
_warning, _severity,
_type, _type,
_component, _component,
message, message,
@ -660,7 +660,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
string content = sources[sourceName]["content"].asString(); string content = sources[sourceName]["content"].asString();
if (!hash.empty() && !hashMatchesContent(hash, content)) if (!hash.empty() && !hashMatchesContent(hash, content))
ret.errors.append(formatError( ret.errors.append(formatError(
false, Error::Severity::Error,
"IOError", "IOError",
"general", "general",
"Mismatch between content and supplied hash for \"" + sourceName + "\"" "Mismatch between content and supplied hash for \"" + sourceName + "\""
@ -685,7 +685,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
{ {
if (!hash.empty() && !hashMatchesContent(hash, result.responseOrErrorMessage)) if (!hash.empty() && !hashMatchesContent(hash, result.responseOrErrorMessage))
ret.errors.append(formatError( ret.errors.append(formatError(
false, Error::Severity::Error,
"IOError", "IOError",
"general", "general",
"Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.asString() + "\"" "Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.asString() + "\""
@ -705,7 +705,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
{ {
/// If the import succeeded, let mark all the others as warnings, otherwise all of them are errors. /// If the import succeeded, let mark all the others as warnings, otherwise all of them are errors.
ret.errors.append(formatError( ret.errors.append(formatError(
found ? true : false, found ? Error::Severity::Warning : Error::Severity::Error,
"IOError", "IOError",
"general", "general",
failure failure
@ -1058,7 +1058,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
compilerStack, compilerStack,
*error, *error,
err.type() == Error::Type::Warning, Error::errorSeverity(err.type()),
err.typeName(), err.typeName(),
"general", "general",
"", "",
@ -1072,7 +1072,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
compilerStack, compilerStack,
_error, _error,
false, Error::Severity::Error,
_error.typeName(), _error.typeName(),
"general", "general",
"Uncaught error: " "Uncaught error: "
@ -1082,7 +1082,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (FatalError const& _exception) catch (FatalError const& _exception)
{ {
errors.append(formatError( errors.append(formatError(
false, Error::Severity::Error,
"FatalError", "FatalError",
"general", "general",
"Uncaught fatal error: " + boost::diagnostic_information(_exception) "Uncaught fatal error: " + boost::diagnostic_information(_exception)
@ -1093,7 +1093,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
compilerStack, compilerStack,
_exception, _exception,
false, Error::Severity::Error,
"CompilerError", "CompilerError",
"general", "general",
"Compiler error (" + _exception.lineInfo() + ")" "Compiler error (" + _exception.lineInfo() + ")"
@ -1104,7 +1104,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
compilerStack, compilerStack,
_exception, _exception,
false, Error::Severity::Error,
"InternalCompilerError", "InternalCompilerError",
"general", "general",
"Internal compiler error (" + _exception.lineInfo() + ")" "Internal compiler error (" + _exception.lineInfo() + ")"
@ -1115,7 +1115,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
compilerStack, compilerStack,
_exception, _exception,
false, Error::Severity::Error,
"UnimplementedFeatureError", "UnimplementedFeatureError",
"general", "general",
"Unimplemented feature (" + _exception.lineInfo() + ")" "Unimplemented feature (" + _exception.lineInfo() + ")"
@ -1126,7 +1126,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
compilerStack, compilerStack,
_exception, _exception,
false, Error::Severity::Error,
"YulException", "YulException",
"general", "general",
"Yul exception" "Yul exception"
@ -1137,7 +1137,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
compilerStack, compilerStack,
_exception, _exception,
false, Error::Severity::Error,
"SMTLogicException", "SMTLogicException",
"general", "general",
"SMT logic exception" "SMT logic exception"
@ -1146,7 +1146,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (util::Exception const& _exception) catch (util::Exception const& _exception)
{ {
errors.append(formatError( errors.append(formatError(
false, Error::Severity::Error,
"Exception", "Exception",
"general", "general",
"Exception during compilation: " + boost::diagnostic_information(_exception) "Exception during compilation: " + boost::diagnostic_information(_exception)
@ -1155,7 +1155,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (std::exception const& _e) catch (std::exception const& _e)
{ {
errors.append(formatError( errors.append(formatError(
false, Error::Severity::Error,
"Exception", "Exception",
"general", "general",
"Unknown exception during compilation" + (_e.what() ? ": " + string(_e.what()) : ".") "Unknown exception during compilation" + (_e.what() ? ": " + string(_e.what()) : ".")
@ -1164,7 +1164,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (...) catch (...)
{ {
errors.append(formatError( errors.append(formatError(
false, Error::Severity::Error,
"Exception", "Exception",
"general", "general",
"Unknown exception during compilation." "Unknown exception during compilation."
@ -1345,7 +1345,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
errors.append(formatErrorWithException( errors.append(formatErrorWithException(
stack, stack,
*error, *error,
err->type() == Error::Type::Warning, Error::errorSeverity(err->type()),
err->typeName(), err->typeName(),
"general", "general",
"" ""
@ -1357,7 +1357,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
// TODO: move this warning to AssemblyStack // TODO: move this warning to AssemblyStack
output["errors"] = Json::arrayValue; output["errors"] = Json::arrayValue;
output["errors"].append(formatError(true, "Warning", "general", "Yul is still experimental. Please use the output with care.")); output["errors"].append(formatError(Error::Severity::Warning, "Warning", "general", "Yul is still experimental. Please use the output with care."));
string contractName = stack.parserResult()->name.str(); string contractName = stack.parserResult()->name.str();

View File

@ -226,7 +226,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False):
old_source_only_ids = { old_source_only_ids = {
"1584", "1823", "1584", "1823",
"1988", "2066", "3356", "1988", "2066", "2833", "3356",
"3893", "3996", "4010", "4802", "3893", "3996", "4010", "4802",
"5272", "5622", "7128", "7400", "5272", "5622", "7128", "7400",
"7589", "7593", "7649", "7710", "7589", "7593", "7649", "7710",

View File

@ -976,7 +976,7 @@ bool CommandLineInterface::assemble(yul::AssemblyStack::Language _language, yul:
m_hasOutput = true; m_hasOutput = true;
formatter.printErrorInformation(*error); formatter.printErrorInformation(*error);
} }
if (!Error::containsOnlyWarnings(stack.errors())) if (Error::containsErrors(stack.errors()))
successful = false; successful = false;
} }

View File

@ -75,24 +75,24 @@ AnalysisFramework::parseAnalyseAndReturnError(
return make_pair(&compiler().ast(""), std::move(errors)); return make_pair(&compiler().ast(""), std::move(errors));
} }
ErrorList AnalysisFramework::filterErrors(ErrorList const& _errorList, bool _includeWarnings) const ErrorList AnalysisFramework::filterErrors(ErrorList const& _errorList, bool _includeWarningsAndInfos) const
{ {
ErrorList errors; ErrorList errors;
for (auto const& currentError: _errorList) for (auto const& currentError: _errorList)
{ {
solAssert(currentError->comment(), ""); solAssert(currentError->comment(), "");
if (currentError->type() == Error::Type::Warning) if (!Error::isError(currentError->type()))
{ {
if (!_includeWarnings) if (!_includeWarningsAndInfos)
continue; continue;
bool ignoreWarning = false; bool ignoreWarningsAndInfos = false;
for (auto const& filter: m_warningsToFilter) for (auto const& filter: m_warningsToFilter)
if (currentError->comment()->find(filter) == 0) if (currentError->comment()->find(filter) == 0)
{ {
ignoreWarning = true; ignoreWarningsAndInfos = true;
break; break;
} }
if (ignoreWarning) if (ignoreWarningsAndInfos)
continue; continue;
} }

View File

@ -66,8 +66,8 @@ protected:
std::string const& _signature std::string const& _signature
); );
// filter out the warnings in m_warningsToFilter or all warnings if _includeWarnings is false // filter out the warnings in m_warningsToFilter or all warnings and infos if _includeWarningsAndInfos is false
langutil::ErrorList filterErrors(langutil::ErrorList const& _errorList, bool _includeWarnings) const; langutil::ErrorList filterErrors(langutil::ErrorList const& _errorList, bool _includeWarningsAndInfos) const;
std::vector<std::string> m_warningsToFilter = {"This is a pre-release compiler version"}; std::vector<std::string> m_warningsToFilter = {"This is a pre-release compiler version"};
std::vector<std::string> m_messagesToCut = {"Source file requires different compiler version (current compiler is"}; std::vector<std::string> m_messagesToCut = {"Source file requires different compiler version (current compiler is"};

View File

@ -67,20 +67,20 @@ evmasm::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
GlobalContext globalContext; GlobalContext globalContext;
NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter);
DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion()); DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion());
solAssert(Error::containsOnlyWarnings(errorReporter.errors()), ""); solAssert(!Error::containsErrors(errorReporter.errors()), "");
resolver.registerDeclarations(*sourceUnit); resolver.registerDeclarations(*sourceUnit);
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*sourceUnit)); BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*sourceUnit));
if (!Error::containsOnlyWarnings(errorReporter.errors())) if (Error::containsErrors(errorReporter.errors()))
return AssemblyItems(); return AssemblyItems();
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
{ {
BOOST_REQUIRE_NO_THROW(declarationTypeChecker.check(*node)); BOOST_REQUIRE_NO_THROW(declarationTypeChecker.check(*node));
if (!Error::containsOnlyWarnings(errorReporter.errors())) if (Error::containsErrors(errorReporter.errors()))
return AssemblyItems(); return AssemblyItems();
} }
TypeChecker checker(solidity::test::CommonOptions::get().evmVersion(), errorReporter); TypeChecker checker(solidity::test::CommonOptions::get().evmVersion(), errorReporter);
BOOST_REQUIRE_NO_THROW(checker.checkTypeRequirements(*sourceUnit)); BOOST_REQUIRE_NO_THROW(checker.checkTypeRequirements(*sourceUnit));
if (!Error::containsOnlyWarnings(errorReporter.errors())) if (Error::containsErrors(errorReporter.errors()))
return AssemblyItems(); return AssemblyItems();
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))

View File

@ -128,7 +128,7 @@ void parsePrintCompare(string const& _source, bool _canWarn = false)
AssemblyStack stack(solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::Assembly, OptimiserSettings::none()); AssemblyStack stack(solidity::test::CommonOptions::get().evmVersion(), AssemblyStack::Language::Assembly, OptimiserSettings::none());
BOOST_REQUIRE(stack.parseAndAnalyze("", _source)); BOOST_REQUIRE(stack.parseAndAnalyze("", _source));
if (_canWarn) if (_canWarn)
BOOST_REQUIRE(Error::containsOnlyWarnings(stack.errors())); BOOST_REQUIRE(!Error::containsErrors(stack.errors()));
else else
BOOST_REQUIRE(stack.errors().empty()); BOOST_REQUIRE(stack.errors().empty());
string expectation = "object \"object\" {\n code " + boost::replace_all_copy(_source, "\n", "\n ") + "\n}\n"; string expectation = "object \"object\" {\n code " + boost::replace_all_copy(_source, "\n", "\n ") + "\n}\n";

View File

@ -74,7 +74,7 @@ bool successParse(std::string const& _source)
if (Error::containsErrorOfType(errors, Error::Type::ParserError)) if (Error::containsErrorOfType(errors, Error::Type::ParserError))
return false; return false;
BOOST_CHECK(Error::containsOnlyWarnings(errors)); BOOST_CHECK(!Error::containsErrors(errors));
return true; return true;
} }

View File

@ -41,6 +41,19 @@ namespace solidity::frontend::test
namespace namespace
{ {
langutil::Error::Severity str2Severity(string const& _cat)
{
map<string, langutil::Error::Severity> cats{
{"info", langutil::Error::Severity::Info},
{"Info", langutil::Error::Severity::Info},
{"warning", langutil::Error::Severity::Warning},
{"Warning", langutil::Error::Severity::Warning},
{"error", langutil::Error::Severity::Error},
{"Error", langutil::Error::Severity::Error}
};
return cats.at(_cat);
}
/// Helper to match a specific error type and message /// Helper to match a specific error type and message
bool containsError(Json::Value const& _compilerResult, string const& _type, string const& _message) bool containsError(Json::Value const& _compilerResult, string const& _type, string const& _message)
{ {
@ -68,7 +81,7 @@ bool containsAtMostWarnings(Json::Value const& _compilerResult)
{ {
BOOST_REQUIRE(error.isObject()); BOOST_REQUIRE(error.isObject());
BOOST_REQUIRE(error["severity"].isString()); BOOST_REQUIRE(error["severity"].isString());
if (error["severity"].asString() != "warning") if (langutil::Error::isError(str2Severity(error["severity"].asString())))
return false; return false;
} }

View File

@ -91,7 +91,7 @@ void SyntaxTest::parseAndAnalyze()
return error->type() == Error::Type::CodeGenerationError; return error->type() == Error::Type::CodeGenerationError;
}); });
auto errorCount = count_if(errors.cbegin(), errors.cend(), [](auto const& error) { auto errorCount = count_if(errors.cbegin(), errors.cend(), [](auto const& error) {
return error->type() != Error::Type::Warning; return Error::isError(error->type());
}); });
// failing compilation after successful analysis is a rare case, // failing compilation after successful analysis is a rare case,
// it assumes that errors contain exactly one error, and the error is of type Error::Type::CodeGenerationError // it assumes that errors contain exactly one error, and the error is of type Error::Type::CodeGenerationError

View File

@ -200,7 +200,7 @@ TestCase::TestResult ControlFlowGraphTest::run(ostream& _stream, string const& _
{ {
ErrorList errors; ErrorList errors;
auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); auto [object, analysisInfo] = parse(m_source, *m_dialect, errors);
if (!object || !analysisInfo || !Error::containsOnlyWarnings(errors)) if (!object || !analysisInfo || Error::containsErrors(errors))
{ {
AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
return TestResult::FatalError; return TestResult::FatalError;

View File

@ -72,7 +72,7 @@ pair<bool, ErrorList> parse(string const& _source)
return {false, {}}; return {false, {}};
} }
optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarnings = true) optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarningsAndInfos = true)
{ {
bool success; bool success;
ErrorList errors; ErrorList errors;
@ -85,11 +85,11 @@ optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarni
else else
{ {
// If success is true, there might still be an error in the assembly stage. // If success is true, there might still be an error in the assembly stage.
if (_allowWarnings && Error::containsOnlyWarnings(errors)) if (_allowWarningsAndInfos && !Error::containsErrors(errors))
return {}; return {};
else if (!errors.empty()) else if (!errors.empty())
{ {
if (!_allowWarnings) if (!_allowWarningsAndInfos)
BOOST_CHECK_EQUAL(errors.size(), 1); BOOST_CHECK_EQUAL(errors.size(), 1);
return *errors.front(); return *errors.front();
} }
@ -97,15 +97,15 @@ optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarni
return {}; return {};
} }
bool successParse(string const& _source, bool _allowWarnings = true) bool successParse(string const& _source, bool _allowWarningsAndInfos = true)
{ {
return !parseAndReturnFirstError(_source, _allowWarnings); return !parseAndReturnFirstError(_source, _allowWarningsAndInfos);
} }
Error expectError(string const& _source, bool _allowWarnings = false) Error expectError(string const& _source, bool _allowWarningsAndInfos = false)
{ {
auto error = parseAndReturnFirstError(_source, _allowWarnings); auto error = parseAndReturnFirstError(_source, _allowWarningsAndInfos);
BOOST_REQUIRE(error); BOOST_REQUIRE(error);
return *error; return *error;
} }

View File

@ -85,7 +85,7 @@ shared_ptr<Block> parse(string const& _source, Dialect const& _dialect, ErrorRep
return {}; return {};
} }
std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect const& _dialect, bool _allowWarnings = true) std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect const& _dialect, bool _allowWarningsAndInfos = true)
{ {
ErrorList errors; ErrorList errors;
ErrorReporter errorReporter(errors); ErrorReporter errorReporter(errors);
@ -98,11 +98,11 @@ std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect con
else else
{ {
// If success is true, there might still be an error in the assembly stage. // If success is true, there might still be an error in the assembly stage.
if (_allowWarnings && Error::containsOnlyWarnings(errors)) if (_allowWarningsAndInfos && !Error::containsErrors(errors))
return {}; return {};
else if (!errors.empty()) else if (!errors.empty())
{ {
if (!_allowWarnings) if (!_allowWarningsAndInfos)
BOOST_CHECK_EQUAL(errors.size(), 1); BOOST_CHECK_EQUAL(errors.size(), 1);
return *errors.front(); return *errors.front();
} }
@ -110,15 +110,15 @@ std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect con
return {}; return {};
} }
bool successParse(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarnings = true) bool successParse(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = true)
{ {
return !parseAndReturnFirstError(_source, _dialect, _allowWarnings); return !parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos);
} }
Error expectError(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarnings = false) Error expectError(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = false)
{ {
auto error = parseAndReturnFirstError(_source, _dialect, _allowWarnings); auto error = parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos);
BOOST_REQUIRE(error); BOOST_REQUIRE(error);
return *error; return *error;
} }

View File

@ -217,7 +217,7 @@ TestCase::TestResult StackLayoutGeneratorTest::run(ostream& _stream, string cons
{ {
ErrorList errors; ErrorList errors;
auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); auto [object, analysisInfo] = parse(m_source, *m_dialect, errors);
if (!object || !analysisInfo || !Error::containsOnlyWarnings(errors)) if (!object || !analysisInfo || Error::containsErrors(errors))
{ {
AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
return TestResult::FatalError; return TestResult::FatalError;

View File

@ -114,7 +114,7 @@ std::pair<std::shared_ptr<Object>, std::shared_ptr<AsmAnalysisInfo>> YulOptimize
shared_ptr<Object> object; shared_ptr<Object> object;
shared_ptr<AsmAnalysisInfo> analysisInfo; shared_ptr<AsmAnalysisInfo> analysisInfo;
std::tie(object, analysisInfo) = yul::test::parse(_source, *m_dialect, errors); std::tie(object, analysisInfo) = yul::test::parse(_source, *m_dialect, errors);
if (!object || !analysisInfo || !Error::containsOnlyWarnings(errors)) if (!object || !analysisInfo || Error::containsErrors(errors))
{ {
AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
CharStream charStream(_source, ""); CharStream charStream(_source, "");

View File

@ -29,7 +29,7 @@ bytes YulAssembler::assemble()
!m_stack.parseAndAnalyze("source", m_yulProgram) || !m_stack.parseAndAnalyze("source", m_yulProgram) ||
!m_stack.parserResult()->code || !m_stack.parserResult()->code ||
!m_stack.parserResult()->analysisInfo || !m_stack.parserResult()->analysisInfo ||
!langutil::Error::containsOnlyWarnings(m_stack.errors()) langutil::Error::containsErrors(m_stack.errors())
) )
yulAssert(false, "Yul program could not be parsed successfully."); yulAssert(false, "Yul program could not be parsed successfully.");

View File

@ -72,7 +72,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
!stack.parseAndAnalyze("source", yul_source) || !stack.parseAndAnalyze("source", yul_source) ||
!stack.parserResult()->code || !stack.parserResult()->code ||
!stack.parserResult()->analysisInfo || !stack.parserResult()->analysisInfo ||
!Error::containsOnlyWarnings(stack.errors()) Error::containsErrors(stack.errors())
) )
yulAssert(false, "Proto fuzzer generated malformed program"); yulAssert(false, "Proto fuzzer generated malformed program");

View File

@ -71,7 +71,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
!stack.parseAndAnalyze("source", yul_source) || !stack.parseAndAnalyze("source", yul_source) ||
!stack.parserResult()->code || !stack.parserResult()->code ||
!stack.parserResult()->analysisInfo || !stack.parserResult()->analysisInfo ||
!Error::containsOnlyWarnings(stack.errors()) Error::containsErrors(stack.errors())
) )
{ {
SourceReferenceFormatter formatter(std::cout, stack, false, false); SourceReferenceFormatter formatter(std::cout, stack, false, false);