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
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
============================

View File

@ -437,7 +437,7 @@ Output Description
.. code-block:: javascript
{
// Optional: not present if no errors/warnings were encountered
// Optional: not present if no errors/warnings/infos were encountered
"errors": [
{
// Optional: Location within the source file.
@ -460,7 +460,7 @@ Output Description
"type": "TypeError",
// Mandatory: Component where the error originated, such as "general", "ewasm", etc.
"component": "general",
// Mandatory ("error" or "warning")
// Mandatory ("error", "warning" or "info", but please note that this may be extended in the future)
"severity": "error",
// Optional: unique code for the cause of the error
"errorCode": "3141",
@ -604,6 +604,7 @@ Error Types
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.
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:

View File

@ -94,6 +94,16 @@ bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
if (m_warningCount >= c_maxWarningsAllowed)
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
{
m_errorCount++;
@ -242,3 +252,12 @@ void ErrorReporter::docstringParsingError(ErrorId _error, SourceLocation const&
_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
);
void info(ErrorId _error, SourceLocation const& _location, std::string const& _description);
void error(
ErrorId _error,
Error::Type _type,
@ -118,13 +120,13 @@ public:
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
{
return m_errorCount > 0;
}
/// @returns the number of errors (ignores warnings).
/// @returns the number of errors (ignores warnings and infos).
unsigned errorCount() const
{
return m_errorCount;
@ -183,9 +185,11 @@ private:
unsigned m_errorCount = 0;
unsigned m_warningCount = 0;
unsigned m_infoCount = 0;
unsigned const c_maxWarningsAllowed = 256;
unsigned const c_maxErrorsAllowed = 256;
unsigned const c_maxInfosAllowed = 256;
};
}

View File

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

View File

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

View File

@ -104,7 +104,7 @@ protected:
void fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description);
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;
/// Current recursion depth during parsing.
size_t m_recursionDepth = 0;

View File

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

View File

@ -41,7 +41,7 @@ struct LineColumn
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).
LineColumn position; ///< Actual (error) position this source reference is surrounding.
bool multiline = {false}; ///< Indicates whether the actual SourceReference is truncated to one line.
@ -64,12 +64,12 @@ namespace SourceReferenceExtractor
struct Message
{
SourceReference primary;
std::string category; // "Error", "Warning", ...
std::string severity; // "Error", "Warning", "Info", ...
std::vector<SourceReference> secondary;
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);
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)
{
// exception header line
errorColored() << _msg.category;
errorColored() << _msg.severity;
if (m_withErrorIds && _msg.errorId.has_value())
errorColored() << " (" << _msg.errorId.value().error << ")";
messageColored() << ": " << _msg.primary.message << '\n';
@ -181,9 +181,9 @@ void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtracto
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)

View File

@ -52,7 +52,7 @@ 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& _category);
void printExceptionInformation(util::Exception const& _exception, std::string const& _severity);
void printErrorInformation(langutil::ErrorList const& _errors);
void printErrorInformation(Error const& _error);
@ -77,7 +77,7 @@ public:
{
return formatExceptionInformation(
_error,
(_error.type() == Error::Type::Warning) ? "Warning" : "Error",
Error::formatErrorSeverity(Error::errorSeverity(_error.type())),
_charStreamProvider
);
}

View File

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

View File

@ -36,7 +36,7 @@ bool ControlFlowAnalyzer::run()
for (auto& [pair, flow]: m_cfg.allFunctionFlows())
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)

View File

@ -27,7 +27,7 @@ using namespace solidity::frontend;
bool CFG::constructFlow(ASTNode const& _astRoot)
{
_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)
{
_astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
bool PostTypeChecker::finalize()
{
for (auto& checker: m_checkers)
checker->finalize();
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
bool PostTypeChecker::visit(ContractDefinition const& _contractDefinition)

View File

@ -68,5 +68,5 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract)
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)
{
_sourceUnit.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
bool StaticAnalyzer::visit(ContractDefinition const& _contract)

View File

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

View File

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

View File

@ -338,7 +338,7 @@ bool CompilerStack::parse()
Source& source = m_sources[path];
source.ast = parser.parse(*source.charStream);
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
{
source.ast->annotation().path = path;
@ -357,7 +357,7 @@ bool CompilerStack::parse()
m_stackState = Parsed;
else
m_stackState = ParsedAndImported;
if (!Error::containsOnlyWarnings(m_errorReporter.errors()))
if (Error::containsErrors(m_errorReporter.errors()))
m_hasError = true;
storeContractDefinitions();

View File

@ -50,7 +50,7 @@ namespace
{
Json::Value formatError(
bool _warning,
Error::Severity _severity,
string const& _type,
string const& _component,
string const& _message,
@ -62,7 +62,7 @@ Json::Value formatError(
Json::Value error = Json::objectValue;
error["type"] = _type;
error["component"] = _component;
error["severity"] = _warning ? "warning" : "error";
error["severity"] = Error::formatErrorSeverityLowercase(_severity);
error["message"] = _message;
error["formattedMessage"] = (_formattedMessage.length() > 0) ? _formattedMessage : _message;
if (_sourceLocation.isObject())
@ -76,7 +76,7 @@ Json::Value formatFatalError(string const& _type, string const& _message)
{
Json::Value output = Json::objectValue;
output["errors"] = Json::arrayValue;
output["errors"].append(formatError(false, _type, "general", _message));
output["errors"].append(formatError(Error::Severity::Error, _type, "general", _message));
return output;
}
@ -111,7 +111,7 @@ Json::Value formatSecondarySourceLocation(SecondarySourceLocation const* _second
Json::Value formatErrorWithException(
CharStreamProvider const& _charStreamProvider,
util::Exception const& _exception,
bool const& _warning,
Error::Severity _severity,
string const& _type,
string const& _component,
string const& _message,
@ -132,7 +132,7 @@ Json::Value formatErrorWithException(
message = _message;
Json::Value error = formatError(
_warning,
_severity,
_type,
_component,
message,
@ -660,7 +660,7 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
string content = sources[sourceName]["content"].asString();
if (!hash.empty() && !hashMatchesContent(hash, content))
ret.errors.append(formatError(
false,
Error::Severity::Error,
"IOError",
"general",
"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))
ret.errors.append(formatError(
false,
Error::Severity::Error,
"IOError",
"general",
"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.
ret.errors.append(formatError(
found ? true : false,
found ? Error::Severity::Warning : Error::Severity::Error,
"IOError",
"general",
failure
@ -1058,7 +1058,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException(
compilerStack,
*error,
err.type() == Error::Type::Warning,
Error::errorSeverity(err.type()),
err.typeName(),
"general",
"",
@ -1072,7 +1072,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException(
compilerStack,
_error,
false,
Error::Severity::Error,
_error.typeName(),
"general",
"Uncaught error: "
@ -1082,7 +1082,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (FatalError const& _exception)
{
errors.append(formatError(
false,
Error::Severity::Error,
"FatalError",
"general",
"Uncaught fatal error: " + boost::diagnostic_information(_exception)
@ -1093,7 +1093,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException(
compilerStack,
_exception,
false,
Error::Severity::Error,
"CompilerError",
"general",
"Compiler error (" + _exception.lineInfo() + ")"
@ -1104,7 +1104,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException(
compilerStack,
_exception,
false,
Error::Severity::Error,
"InternalCompilerError",
"general",
"Internal compiler error (" + _exception.lineInfo() + ")"
@ -1115,7 +1115,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException(
compilerStack,
_exception,
false,
Error::Severity::Error,
"UnimplementedFeatureError",
"general",
"Unimplemented feature (" + _exception.lineInfo() + ")"
@ -1126,7 +1126,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException(
compilerStack,
_exception,
false,
Error::Severity::Error,
"YulException",
"general",
"Yul exception"
@ -1137,7 +1137,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
errors.append(formatErrorWithException(
compilerStack,
_exception,
false,
Error::Severity::Error,
"SMTLogicException",
"general",
"SMT logic exception"
@ -1146,7 +1146,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (util::Exception const& _exception)
{
errors.append(formatError(
false,
Error::Severity::Error,
"Exception",
"general",
"Exception during compilation: " + boost::diagnostic_information(_exception)
@ -1155,7 +1155,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (std::exception const& _e)
{
errors.append(formatError(
false,
Error::Severity::Error,
"Exception",
"general",
"Unknown exception during compilation" + (_e.what() ? ": " + string(_e.what()) : ".")
@ -1164,7 +1164,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
catch (...)
{
errors.append(formatError(
false,
Error::Severity::Error,
"Exception",
"general",
"Unknown exception during compilation."
@ -1345,7 +1345,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
errors.append(formatErrorWithException(
stack,
*error,
err->type() == Error::Type::Warning,
Error::errorSeverity(err->type()),
err->typeName(),
"general",
""
@ -1357,7 +1357,7 @@ Json::Value StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
// TODO: move this warning to AssemblyStack
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();

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 = {
"1584", "1823",
"1988", "2066", "3356",
"1988", "2066", "2833", "3356",
"3893", "3996", "4010", "4802",
"5272", "5622", "7128", "7400",
"7589", "7593", "7649", "7710",

View File

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

View File

@ -75,24 +75,24 @@ AnalysisFramework::parseAnalyseAndReturnError(
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;
for (auto const& currentError: _errorList)
{
solAssert(currentError->comment(), "");
if (currentError->type() == Error::Type::Warning)
if (!Error::isError(currentError->type()))
{
if (!_includeWarnings)
if (!_includeWarningsAndInfos)
continue;
bool ignoreWarning = false;
bool ignoreWarningsAndInfos = false;
for (auto const& filter: m_warningsToFilter)
if (currentError->comment()->find(filter) == 0)
{
ignoreWarning = true;
ignoreWarningsAndInfos = true;
break;
}
if (ignoreWarning)
if (ignoreWarningsAndInfos)
continue;
}

View File

@ -66,8 +66,8 @@ protected:
std::string const& _signature
);
// filter out the warnings in m_warningsToFilter or all warnings if _includeWarnings is false
langutil::ErrorList filterErrors(langutil::ErrorList const& _errorList, bool _includeWarnings) const;
// filter out the warnings in m_warningsToFilter or all warnings and infos if _includeWarningsAndInfos is false
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_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;
NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter);
DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion());
solAssert(Error::containsOnlyWarnings(errorReporter.errors()), "");
solAssert(!Error::containsErrors(errorReporter.errors()), "");
resolver.registerDeclarations(*sourceUnit);
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*sourceUnit));
if (!Error::containsOnlyWarnings(errorReporter.errors()))
if (Error::containsErrors(errorReporter.errors()))
return AssemblyItems();
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
{
BOOST_REQUIRE_NO_THROW(declarationTypeChecker.check(*node));
if (!Error::containsOnlyWarnings(errorReporter.errors()))
if (Error::containsErrors(errorReporter.errors()))
return AssemblyItems();
}
TypeChecker checker(solidity::test::CommonOptions::get().evmVersion(), errorReporter);
BOOST_REQUIRE_NO_THROW(checker.checkTypeRequirements(*sourceUnit));
if (!Error::containsOnlyWarnings(errorReporter.errors()))
if (Error::containsErrors(errorReporter.errors()))
return AssemblyItems();
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
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());
BOOST_REQUIRE(stack.parseAndAnalyze("", _source));
if (_canWarn)
BOOST_REQUIRE(Error::containsOnlyWarnings(stack.errors()));
BOOST_REQUIRE(!Error::containsErrors(stack.errors()));
else
BOOST_REQUIRE(stack.errors().empty());
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))
return false;
BOOST_CHECK(Error::containsOnlyWarnings(errors));
BOOST_CHECK(!Error::containsErrors(errors));
return true;
}

View File

@ -41,6 +41,19 @@ namespace solidity::frontend::test
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
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["severity"].isString());
if (error["severity"].asString() != "warning")
if (langutil::Error::isError(str2Severity(error["severity"].asString())))
return false;
}

View File

@ -91,7 +91,7 @@ void SyntaxTest::parseAndAnalyze()
return error->type() == Error::Type::CodeGenerationError;
});
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,
// 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;
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;
return TestResult::FatalError;

View File

@ -72,7 +72,7 @@ pair<bool, ErrorList> parse(string const& _source)
return {false, {}};
}
optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarnings = true)
optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarningsAndInfos = true)
{
bool success;
ErrorList errors;
@ -85,11 +85,11 @@ optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarni
else
{
// 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 {};
else if (!errors.empty())
{
if (!_allowWarnings)
if (!_allowWarningsAndInfos)
BOOST_CHECK_EQUAL(errors.size(), 1);
return *errors.front();
}
@ -97,15 +97,15 @@ optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarni
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);
return *error;
}

View File

@ -85,7 +85,7 @@ shared_ptr<Block> parse(string const& _source, Dialect const& _dialect, ErrorRep
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;
ErrorReporter errorReporter(errors);
@ -98,11 +98,11 @@ std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect con
else
{
// 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 {};
else if (!errors.empty())
{
if (!_allowWarnings)
if (!_allowWarningsAndInfos)
BOOST_CHECK_EQUAL(errors.size(), 1);
return *errors.front();
}
@ -110,15 +110,15 @@ std::optional<Error> parseAndReturnFirstError(string const& _source, Dialect con
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);
return *error;
}

View File

@ -217,7 +217,7 @@ TestCase::TestResult StackLayoutGeneratorTest::run(ostream& _stream, string cons
{
ErrorList 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;
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<AsmAnalysisInfo> analysisInfo;
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;
CharStream charStream(_source, "");

View File

@ -29,7 +29,7 @@ bytes YulAssembler::assemble()
!m_stack.parseAndAnalyze("source", m_yulProgram) ||
!m_stack.parserResult()->code ||
!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.");

View File

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