From fc37b4eeb63e6f42e6a6a5bfe85878c288fd69c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 29 Sep 2023 22:07:44 +0200 Subject: [PATCH 1/4] Add Error::parseErrorType() --- liblangutil/Exceptions.cpp | 20 ++++++++++++++++++++ liblangutil/Exceptions.h | 37 +++++++++++++++---------------------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/liblangutil/Exceptions.cpp b/liblangutil/Exceptions.cpp index 118720b74..108acd121 100644 --- a/liblangutil/Exceptions.cpp +++ b/liblangutil/Exceptions.cpp @@ -29,6 +29,26 @@ using namespace solidity; using namespace solidity::langutil; +std::map const Error::m_errorTypeNames = { + {Error::Type::IOError, "IOError"}, + {Error::Type::FatalError, "FatalError"}, + {Error::Type::JSONError, "JSONError"}, + {Error::Type::InternalCompilerError, "InternalCompilerError"}, + {Error::Type::CompilerError, "CompilerError"}, + {Error::Type::Exception, "Exception"}, + {Error::Type::CodeGenerationError, "CodeGenerationError"}, + {Error::Type::DeclarationError, "DeclarationError"}, + {Error::Type::DocstringParsingError, "DocstringParsingError"}, + {Error::Type::ParserError, "ParserError"}, + {Error::Type::SyntaxError, "SyntaxError"}, + {Error::Type::TypeError, "TypeError"}, + {Error::Type::UnimplementedFeatureError, "UnimplementedFeatureError"}, + {Error::Type::YulException, "YulException"}, + {Error::Type::SMTLogicException, "SMTLogicException"}, + {Error::Type::Warning, "Warning"}, + {Error::Type::Info, "Info"}, +}; + Error::Error( ErrorId _errorId, Error::Type _type, std::string const& _description, diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index 65362df31..72ad0c12b 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -33,10 +33,11 @@ #include #include +#include +#include #include #include #include -#include #include namespace solidity::langutil @@ -269,27 +270,17 @@ public: 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(); + return m_errorTypeNames.at(_type); + } + + static std::optional parseErrorType(std::string _name) + { + static std::map const m_errorTypesByName = util::invertMap(m_errorTypeNames); + + if (m_errorTypesByName.count(_name) == 0) + return std::nullopt; + + return m_errorTypesByName.at(_name); } static std::string formatTypeOrSeverity(std::variant _typeOrSeverity) @@ -309,6 +300,8 @@ public: private: ErrorId m_errorId; Type m_type; + + static std::map const m_errorTypeNames; }; } From 81b5387a9f675a5bcd7bd4a28003ba96dcd0e657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 29 Sep 2023 22:08:10 +0200 Subject: [PATCH 2/4] Store Error::Type rather than a string in SyntaxTestError --- test/CommonSyntaxTest.cpp | 14 +++++++++----- test/CommonSyntaxTest.h | 2 +- test/libsolidity/SyntaxTest.cpp | 4 ++-- test/libyul/SyntaxTest.cpp | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index 79b597804..b3c242957 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -114,7 +114,7 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, { assert(static_cast(error.locationStart) <= source.length()); assert(static_cast(error.locationEnd) <= source.length()); - bool isWarning = error.type == "Warning"; + bool isWarning = (error.type == Error::Type::Warning); for (int i = error.locationStart; i < error.locationEnd; i++) if (isWarning) { @@ -192,8 +192,8 @@ void CommonSyntaxTest::printErrorList( for (auto const& error: _errorList) { { - util::AnsiColorized scope(_stream, _formatted, {BOLD, (error.type == "Warning") ? YELLOW : RED}); - _stream << _linePrefix << error.type; + util::AnsiColorized scope(_stream, _formatted, {BOLD, (error.type == Error::Type::Warning) ? YELLOW : RED}); + _stream << _linePrefix << Error::formatErrorType(error.type); if (error.errorId.has_value()) _stream << ' ' << error.errorId->error; _stream << ": "; @@ -246,7 +246,11 @@ vector CommonSyntaxTest::parseExpectations(istream& _stream) auto typeBegin = it; while (it != line.end() && isalpha(*it, locale::classic())) ++it; - string errorType(typeBegin, it); + + std::string errorTypeStr(typeBegin, it); + optional errorType = Error::parseErrorType(errorTypeStr); + if (!errorType.has_value()) + BOOST_THROW_EXCEPTION(runtime_error("Invalid error type: " + errorTypeStr)); skipWhitespace(it, line.end()); @@ -283,7 +287,7 @@ vector CommonSyntaxTest::parseExpectations(istream& _stream) string errorMessage(it, line.end()); expectations.emplace_back(SyntaxTestError{ - std::move(errorType), + errorType.value(), std::move(errorId), std::move(errorMessage), std::move(sourceName), diff --git a/test/CommonSyntaxTest.h b/test/CommonSyntaxTest.h index 606f61a88..fb46c37a6 100644 --- a/test/CommonSyntaxTest.h +++ b/test/CommonSyntaxTest.h @@ -34,7 +34,7 @@ namespace solidity::test struct SyntaxTestError { - std::string type; + langutil::Error::Type type; std::optional errorId; std::string message; std::string sourceName; diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 906391e01..90003768e 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -86,7 +86,7 @@ void SyntaxTest::parseAndAnalyze() catch (UnimplementedFeatureError const& _e) { m_errorList.emplace_back(SyntaxTestError{ - "UnimplementedFeatureError", + Error::Type::UnimplementedFeatureError, nullopt, errorMessage(_e), "", @@ -135,7 +135,7 @@ void SyntaxTest::filterObtainedErrors() } } m_errorList.emplace_back(SyntaxTestError{ - Error::formatErrorType(currentError->type()), + currentError->type(), currentError->errorId(), errorMessage(*currentError), sourceName, diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index cea1d5745..20aadcf19 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -61,7 +61,7 @@ void SyntaxTest::parseAndAnalyze() } m_errorList.emplace_back(SyntaxTestError{ - Error::formatErrorType(error->type()), + error->type(), error->errorId(), errorMessage(*error), name, From 7857562a3bf42de3af0f729deb3ea41dc17fb245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 28 Sep 2023 18:30:26 +0200 Subject: [PATCH 3/4] CommonSyntaxTest: Fix info messages being colored as errors --- libsolutil/AnsiColorized.h | 1 + test/CommonSyntaxTest.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libsolutil/AnsiColorized.h b/libsolutil/AnsiColorized.h index 69d10d727..08b4a4d22 100644 --- a/libsolutil/AnsiColorized.h +++ b/libsolutil/AnsiColorized.h @@ -52,6 +52,7 @@ static constexpr char const* BLUE_BACKGROUND = "\033[44m"; static constexpr char const* MAGENTA_BACKGROUND = "\033[45m"; static constexpr char const* CYAN_BACKGROUND = "\033[46m"; static constexpr char const* WHITE_BACKGROUND = "\033[47m"; +static constexpr char const* GRAY_BACKGROUND = "\033[100m"; // 256-bit-colors (incomplete set) static constexpr char const* RED_BACKGROUND_256 = "\033[48;5;160m"; diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index b3c242957..d26f60ccc 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -114,11 +114,18 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, { assert(static_cast(error.locationStart) <= source.length()); assert(static_cast(error.locationEnd) <= source.length()); - bool isWarning = (error.type == Error::Type::Warning); for (int i = error.locationStart; i < error.locationEnd; i++) - if (isWarning) + if (error.type == Error::Type::Info) { if (sourceFormatting[static_cast(i)] == util::formatting::RESET) + sourceFormatting[static_cast(i)] = util::formatting::GRAY_BACKGROUND; + } + else if (error.type == Error::Type::Warning) + { + if ( + sourceFormatting[static_cast(i)] == util::formatting::RESET || + sourceFormatting[static_cast(i)] == util::formatting::GRAY_BACKGROUND + ) sourceFormatting[static_cast(i)] = util::formatting::ORANGE_BACKGROUND_256; } else @@ -192,7 +199,11 @@ void CommonSyntaxTest::printErrorList( for (auto const& error: _errorList) { { - util::AnsiColorized scope(_stream, _formatted, {BOLD, (error.type == Error::Type::Warning) ? YELLOW : RED}); + util::AnsiColorized scope( + _stream, + _formatted, + {BOLD, error.type == Error::Type::Info ? WHITE : (error.type == Error::Type::Warning ? YELLOW : RED)} + ); _stream << _linePrefix << Error::formatErrorType(error.type); if (error.errorId.has_value()) _stream << ' ' << error.errorId->error; From 6c1ed8c2d0a4c8dc28d90c16b49a64e90faee7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 29 Sep 2023 22:43:49 +0200 Subject: [PATCH 4/4] Reuse color definitions between SourceReferenceFormatter and CommonSyntaxTest --- liblangutil/SourceReferenceFormatter.cpp | 35 ++++++++++++++++-------- liblangutil/SourceReferenceFormatter.h | 9 ++++++ test/CommonSyntaxTest.cpp | 33 +++++++++++----------- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/liblangutil/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp index 76cb1df61..0e84242a7 100644 --- a/liblangutil/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -55,6 +55,28 @@ std::string SourceReferenceFormatter::formatErrorInformation(Error const& _error ); } +char const* SourceReferenceFormatter::errorTextColor(Error::Severity _severity) +{ + switch (_severity) + { + case Error::Severity::Error: return RED; + case Error::Severity::Warning: return YELLOW; + case Error::Severity::Info: return WHITE; + } + util::unreachable(); +} + +char const* SourceReferenceFormatter::errorHighlightColor(Error::Severity _severity) +{ + switch (_severity) + { + case Error::Severity::Error: return RED_BACKGROUND; + case Error::Severity::Warning: return ORANGE_BACKGROUND_256; + case Error::Severity::Info: return GRAY_BACKGROUND; + } + util::unreachable(); +} + AnsiColorized SourceReferenceFormatter::normalColored() const { return AnsiColorized(m_stream, m_colored, {WHITE}); @@ -67,18 +89,7 @@ AnsiColorized SourceReferenceFormatter::frameColored() 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; - - 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}); + return AnsiColorized(m_stream, m_colored, {BOLD, errorTextColor(_severity)}); } AnsiColorized SourceReferenceFormatter::messageColored() const diff --git a/liblangutil/SourceReferenceFormatter.h b/liblangutil/SourceReferenceFormatter.h index 91f1d7ddd..46cd97490 100644 --- a/liblangutil/SourceReferenceFormatter.h +++ b/liblangutil/SourceReferenceFormatter.h @@ -118,6 +118,15 @@ public: static std::string formatErrorInformation(Error const& _error, CharStream const& _charStream); + /// The default text color for printing error messages of a given severity in the terminal. + /// Only suitable for color schemes with a dark background. + static char const* errorTextColor(Error::Severity _severity); + + /// The default background color for highlighting source fragments corresponding to an error + /// of a given severity in the terminal. + /// Only suitable for color schemes with a light text. + static char const* errorHighlightColor(Error::Severity _severity); + private: util::AnsiColorized normalColored() const; util::AnsiColorized frameColored() const; diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index d26f60ccc..209a041ff 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -19,11 +19,16 @@ #include #include #include + +#include + #include + #include #include #include #include + #include #include #include @@ -115,21 +120,17 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, assert(static_cast(error.locationStart) <= source.length()); assert(static_cast(error.locationEnd) <= source.length()); for (int i = error.locationStart; i < error.locationEnd; i++) - if (error.type == Error::Type::Info) - { - if (sourceFormatting[static_cast(i)] == util::formatting::RESET) - sourceFormatting[static_cast(i)] = util::formatting::GRAY_BACKGROUND; - } - else if (error.type == Error::Type::Warning) - { - if ( - sourceFormatting[static_cast(i)] == util::formatting::RESET || - sourceFormatting[static_cast(i)] == util::formatting::GRAY_BACKGROUND - ) - sourceFormatting[static_cast(i)] = util::formatting::ORANGE_BACKGROUND_256; - } - else - sourceFormatting[static_cast(i)] = util::formatting::RED_BACKGROUND; + { + char const*& cellFormat = sourceFormatting[static_cast(i)]; + char const* infoBgColor = SourceReferenceFormatter::errorHighlightColor(Error::Severity::Info); + + if ( + (error.type != Error::Type::Warning && error.type != Error::Type::Info) || + (error.type == Error::Type::Warning && (cellFormat == RESET || cellFormat == infoBgColor)) || + (error.type == Error::Type::Info && cellFormat == RESET) + ) + cellFormat = SourceReferenceFormatter::errorHighlightColor(Error::errorSeverity(error.type)); + } } _stream << _linePrefix << sourceFormatting.front() << source.front(); @@ -202,7 +203,7 @@ void CommonSyntaxTest::printErrorList( util::AnsiColorized scope( _stream, _formatted, - {BOLD, error.type == Error::Type::Info ? WHITE : (error.type == Error::Type::Warning ? YELLOW : RED)} + {BOLD, SourceReferenceFormatter::errorTextColor(Error::errorSeverity(error.type))} ); _stream << _linePrefix << Error::formatErrorType(error.type); if (error.errorId.has_value())