From 996e9cacd018f8ba9da3c77cd4c8dde34f855305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 1 Aug 2023 13:46:58 +0200 Subject: [PATCH] Generalize existing functions for indenting and prefixing --- libsolutil/StringUtils.cpp | 35 ++++++++++++++++++++++++++++ libsolutil/StringUtils.h | 34 ++++++++++++++++++++++++++- libyul/Object.cpp | 16 +------------ test/CommonSyntaxTest.cpp | 8 +++---- test/TestCase.cpp | 23 +++++------------- test/TestCase.h | 1 - test/libsolidity/ASTJSONTest.cpp | 21 ++++------------- test/libsolidity/GasTest.cpp | 8 ------- test/libsolidity/GasTest.h | 1 - test/libsolidity/NatspecJSONTest.cpp | 5 ++-- test/libsolidity/SemanticTest.cpp | 7 ++---- test/libyul/YulOptimizerTest.cpp | 3 ++- 12 files changed, 89 insertions(+), 73 deletions(-) diff --git a/libsolutil/StringUtils.cpp b/libsolutil/StringUtils.cpp index 1dc86714d..f5d2bbfb3 100644 --- a/libsolutil/StringUtils.cpp +++ b/libsolutil/StringUtils.cpp @@ -23,6 +23,10 @@ */ #include + +#include + +#include #include #include @@ -190,3 +194,34 @@ std::string solidity::util::formatNumberReadable(bigint const& _value, bool _use return sign + str; } +std::string solidity::util::prefixLines( + std::string const& _input, + std::string const& _prefix, + bool _trimPrefix +) +{ + std::ostringstream output; + printPrefixed(output, _input, _prefix, _trimPrefix, false /* _ensureFinalNewline */); + return output.str(); +} + +void solidity::util::printPrefixed( + std::ostream& _output, + std::string const& _input, + std::string const& _prefix, + bool _trimPrefix, + bool _ensureFinalNewline +) +{ + std::istringstream input(_input); + std::string line; + while (std::getline(input, line)) + { + if (line.empty() && _trimPrefix) + _output << boost::trim_right_copy(_prefix); + else + _output << _prefix << line; + if (!input.eof() || _ensureFinalNewline) + _output << '\n'; + } +} diff --git a/libsolutil/StringUtils.h b/libsolutil/StringUtils.h index 0d5bc7839..77ffe6735 100644 --- a/libsolutil/StringUtils.h +++ b/libsolutil/StringUtils.h @@ -168,7 +168,7 @@ inline bool isDigit(char _c) return isdigit(_c, std::locale::classic()); } -// Checks if character is printable using classic "C" locale +/// Checks if character is printable using classic "C" locale /// @param _c character to be checked /// @return true if _c is a printable character, false otherwise. inline bool isPrint(char _c) @@ -176,4 +176,36 @@ inline bool isPrint(char _c) return isprint(_c, std::locale::classic()); } +/// Adds a prefix to every line in the input. +/// @see printPrefixed() +std::string prefixLines( + std::string const& _input, + std::string const& _prefix, + bool _trimPrefix = true +); + +/// Prints to a stream, adding a prefix to every line in the input. +/// Assumes \n as the line separator. +/// @param _trimPrefix If true, the function avoids introducing trailing whitespace on empty lines. +/// This is achieved by removing trailing spaces from the prefix on such lines. +/// Note that tabs and newlines are not removed, only spaces are. +/// @param _finalNewline If true, an extra \n will be printed at the end of @a _input if it does +/// not already end with one. +void printPrefixed( + std::ostream& _output, + std::string const& _input, + std::string const& _prefix, + bool _trimPrefix = true, + bool _ensureFinalNewline = true +); + +/// Adds a standard indent of 4 spaces to every line in the input. +/// Assumes \n as the line separator. +/// @param _indentEmptyLines If true, the indent will be applied to empty lines as well, resulting +/// such lines containing trailing whitespace. +inline std::string indent(std::string const& _input, bool _indentEmptyLines = false) +{ + return prefixLines(_input, " ", !_indentEmptyLines); +} + } diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 83ee66a3b..96d60fc77 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -30,8 +30,6 @@ #include #include -#include -#include #include @@ -40,18 +38,6 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -namespace -{ - -std::string indent(std::string const& _input) -{ - if (_input.empty()) - return _input; - return boost::replace_all_copy(" " + _input, "\n", "\n "); -} - -} - std::string Data::toString(Dialect const*, DebugInfoSelection const&, CharStreamProvider const*) const { return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\""; @@ -86,7 +72,7 @@ std::string Object::toString( for (auto const& obj: subObjects) inner += "\n" + obj->toString(_dialect, _debugInfoSelection, _soliditySourceProvider); - return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; + return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner, true /* _indentEmptyLines */) + "\n}"; } Json::Value Data::toJson() const diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index 79b597804..8e546017f 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -144,11 +145,8 @@ void CommonSyntaxTest::printSource(ostream& _stream, string const& _linePrefix, else { if (outputSourceNames) - _stream << _linePrefix << "==== Source: " + name << " ====" << endl; - stringstream stream(source); - string line; - while (getline(stream, line)) - _stream << _linePrefix << line << endl; + printPrefixed(_stream, "==== Source: " + name + " ====", _linePrefix); + printPrefixed(_stream, source, _linePrefix); } } diff --git a/test/TestCase.cpp b/test/TestCase.cpp index 059d2ab70..51608bd4a 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -20,8 +20,8 @@ #include #include +#include -#include #include #include @@ -31,6 +31,7 @@ using namespace std; using namespace solidity; using namespace solidity::frontend; using namespace solidity::frontend::test; +using namespace solidity::util; void TestCase::printSettings(ostream& _stream, const string& _linePrefix, const bool) { @@ -69,26 +70,14 @@ void TestCase::expect(string::iterator& _it, string::iterator _end, string::valu ++_it; } -void TestCase::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const -{ - stringstream output(_output); - string line; - while (getline(output, line)) - if (line.empty()) - // Avoid trailing spaces. - _stream << boost::trim_right_copy(_linePrefix) << endl; - else - _stream << _linePrefix << line << endl; -} - void TestCase::printSource(ostream& _stream, string const& _linePrefix, bool const) const { - printIndented(_stream, m_source, _linePrefix); + printPrefixed(_stream, m_source, _linePrefix); } void TestCase::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const { - printIndented(_stream, m_obtainedResult, _linePrefix); + printPrefixed(_stream, m_obtainedResult, _linePrefix); } TestCase::TestResult TestCase::checkResult(std::ostream& _stream, const std::string& _linePrefix, bool const _formatted) @@ -99,10 +88,10 @@ TestCase::TestResult TestCase::checkResult(std::ostream& _stream, const std::str util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) << _linePrefix << "Expected result:" << endl; // TODO could compute a simple diff with highlighted lines - printIndented(_stream, m_expectation, nextIndentLevel); + printPrefixed(_stream, m_expectation, nextIndentLevel); util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) << _linePrefix << "Obtained result:" << endl; - printIndented(_stream, m_obtainedResult, nextIndentLevel); + printPrefixed(_stream, m_obtainedResult, nextIndentLevel); return TestResult::Failure; } return TestResult::Success; diff --git a/test/TestCase.h b/test/TestCase.h index f631bea8d..301dbfb65 100644 --- a/test/TestCase.h +++ b/test/TestCase.h @@ -100,7 +100,6 @@ protected: ++_it; } - void printIndented(std::ostream& _stream, std::string const& _output, std::string const& _linePrefix = "") const; TestCase::TestResult checkResult(std::ostream& _stream, const std::string& _linePrefix, bool const _formatted); std::string m_source; diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp index a318eacee..daf4a9ea4 100644 --- a/test/libsolidity/ASTJSONTest.cpp +++ b/test/libsolidity/ASTJSONTest.cpp @@ -270,12 +270,7 @@ bool ASTJSONTest::runTest( "Expected result" << (!_variant.name().empty() ? " (" + _variant.name() + "):" : ":") << std::endl; - { - std::istringstream stream(_variant.expectation); - std::string line; - while (getline(stream, line)) - _stream << nextIndentLevel << line << std::endl; - } + printPrefixed(_stream, _variant.expectation, nextIndentLevel); _stream << std::endl; AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << @@ -283,12 +278,7 @@ bool ASTJSONTest::runTest( "Obtained result" << (!_variant.name().empty() ? " (" + _variant.name() + "):" : ":") << std::endl; - { - std::istringstream stream(_variant.result); - std::string line; - while (getline(stream, line)) - _stream << nextIndentLevel << line << std::endl; - } + printPrefixed(_stream, _variant.result, nextIndentLevel); _stream << std::endl; return false; } @@ -301,11 +291,8 @@ void ASTJSONTest::printSource(std::ostream& _stream, std::string const& _linePre for (auto const& source: m_sources) { if (m_sources.size() > 1 || source.first != "a") - _stream << _linePrefix << sourceDelimiter << source.first << " ====" << std::endl << std::endl; - std::stringstream stream(source.second); - std::string line; - while (getline(stream, line)) - _stream << _linePrefix << line << std::endl; + printPrefixed(_stream, sourceDelimiter + source.first + " ====\n", _linePrefix); + printPrefixed(_stream, source.second, _linePrefix); _stream << std::endl; } } diff --git a/test/libsolidity/GasTest.cpp b/test/libsolidity/GasTest.cpp index 5d8a69497..73aa780e4 100644 --- a/test/libsolidity/GasTest.cpp +++ b/test/libsolidity/GasTest.cpp @@ -158,11 +158,3 @@ TestCase::TestResult GasTest::run(std::ostream& _stream, std::string const& _lin return TestResult::Failure; } } - -void GasTest::printSource(std::ostream& _stream, std::string const& _linePrefix, bool) const -{ - std::string line; - std::istringstream input(m_source); - while (getline(input, line)) - _stream << _linePrefix << line << std::endl; -} diff --git a/test/libsolidity/GasTest.h b/test/libsolidity/GasTest.h index a04976cd5..1337ae3f6 100644 --- a/test/libsolidity/GasTest.h +++ b/test/libsolidity/GasTest.h @@ -41,7 +41,6 @@ public: TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool _formatted = false) override; - void printSource(std::ostream &_stream, std::string const &_linePrefix = "", bool _formatted = false) const override; void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; protected: diff --git a/test/libsolidity/NatspecJSONTest.cpp b/test/libsolidity/NatspecJSONTest.cpp index 434d5b392..53f0db86f 100644 --- a/test/libsolidity/NatspecJSONTest.cpp +++ b/test/libsolidity/NatspecJSONTest.cpp @@ -100,8 +100,9 @@ void NatspecJSONTest::printExpectedResult(ostream& _stream, string const& _lineP if (!m_expectedNatspecJSON.empty()) { _stream << _linePrefix << "----" << endl; - printIndented(_stream, formatNatspecExpectations(m_expectedNatspecJSON), _linePrefix); + printPrefixed(_stream, formatNatspecExpectations(m_expectedNatspecJSON), _linePrefix); } + } void NatspecJSONTest::printObtainedResult(ostream& _stream, string const& _linePrefix, bool _formatted) const @@ -114,7 +115,7 @@ void NatspecJSONTest::printObtainedResult(ostream& _stream, string const& _lineP _stream << _linePrefix << "----" << endl; // TODO: Diff both versions and highlight differences. // We should have a helper for doing that in newly defined test cases without much effort. - printIndented(_stream, formatNatspecExpectations(natspecJSON), _linePrefix); + printPrefixed(_stream, formatNatspecExpectations(natspecJSON), _linePrefix); } } diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index f59c61ad8..25113b689 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -647,11 +647,8 @@ void SemanticTest::printSource(std::ostream& _stream, std::string const& _linePr else { if (outputNames) - _stream << _linePrefix << "==== Source: " + name << " ====" << std::endl; - std::stringstream stream(source); - std::string line; - while (getline(stream, line)) - _stream << _linePrefix << line << std::endl; + printPrefixed(_stream, "==== Source: " + name + " ====", _linePrefix); + printPrefixed(_stream, source, _linePrefix); } } } diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index b50bcb38e..6d7297c2c 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -31,6 +31,7 @@ #include #include +#include #include @@ -86,7 +87,7 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line { util::AnsiColorized(_stream, _formatted, {util::formatting::BOLD, util::formatting::CYAN}) << _linePrefix << "Result after the optimiser:" << endl; - printIndented(_stream, printed, _linePrefix + " "); + printPrefixed(_stream, printed, _linePrefix + " "); return TestResult::FatalError; }