diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt
index 201429bb7..f97d61b67 100644
--- a/libsolutil/CMakeLists.txt
+++ b/libsolutil/CMakeLists.txt
@@ -13,8 +13,6 @@ set(sources
ErrorCodes.h
FixedHash.h
FunctionSelector.h
- IndentedWriter.cpp
- IndentedWriter.h
IpfsHash.cpp
IpfsHash.h
JSON.cpp
diff --git a/libsolutil/IndentedWriter.cpp b/libsolutil/IndentedWriter.cpp
deleted file mode 100644
index b2a3c06c9..000000000
--- a/libsolutil/IndentedWriter.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- This file is part of solidity.
-
- solidity is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- solidity is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with solidity. If not, see .
-*/
-// SPDX-License-Identifier: GPL-3.0
-/**
- * @date 2017
- * Indented text writer.
- */
-
-#include
-#include
-
-using namespace solidity::util;
-
-std::string IndentedWriter::format() const
-{
- std::string result;
- for (auto const& line: m_lines)
- result += std::string(line.indentation * 4, ' ') + line.contents + "\n";
- return result;
-}
-
-void IndentedWriter::newLine()
-{
- if (!m_lines.back().contents.empty())
- m_lines.emplace_back(Line{std::string(), m_lines.back().indentation});
-}
-
-void IndentedWriter::indent()
-{
- newLine();
- m_lines.back().indentation++;
-}
-
-void IndentedWriter::unindent()
-{
- newLine();
- assertThrow(m_lines.back().indentation > 0, IndentedWriterError, "Negative indentation.");
- m_lines.back().indentation--;
-}
-
-void IndentedWriter::add(std::string const& _str)
-{
- m_lines.back().contents += _str;
-}
-
-void IndentedWriter::addLine(std::string const& _line)
-{
- newLine();
- add(_line);
- newLine();
-}
diff --git a/libsolutil/IndentedWriter.h b/libsolutil/IndentedWriter.h
deleted file mode 100644
index 47e2817fa..000000000
--- a/libsolutil/IndentedWriter.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- This file is part of solidity.
-
- solidity is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- solidity is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with solidity. If not, see .
-*/
-// SPDX-License-Identifier: GPL-3.0
-/**
- * @date 2017
- * Indented text writer.
- */
-
-#pragma once
-
-#include
-#include
-
-#include
-
-namespace solidity::util
-{
-
-DEV_SIMPLE_EXCEPTION(IndentedWriterError);
-
-class IndentedWriter
-{
-public:
- // Returns the formatted output.
- std::string format() const;
-
- // Go one indentation level in.
- void indent();
-
- // Go one indentation level out.
- void unindent();
-
- // Add text.
- void add(std::string const& _str);
-
- // Add text with new line.
- void addLine(std::string const& _line);
-
- // Add new line.
- void newLine();
-
-private:
- struct Line
- {
- std::string contents;
- unsigned indentation;
- };
-
- std::vector m_lines{{std::string(), 0}};
-};
-
-}
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..0d3d66c8e 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) + "\"";
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f8242db7a..f32a14d91 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -33,7 +33,6 @@ set(libsolutil_sources
libsolutil/CommonIO.cpp
libsolutil/FixedHash.cpp
libsolutil/FunctionSelector.cpp
- libsolutil/IndentedWriter.cpp
libsolutil/IpfsHash.cpp
libsolutil/IterateReplacing.cpp
libsolutil/JSON.cpp
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/libsolutil/IndentedWriter.cpp b/test/libsolutil/IndentedWriter.cpp
deleted file mode 100644
index 94997c842..000000000
--- a/test/libsolutil/IndentedWriter.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- This file is part of solidity.
-
- solidity is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- solidity is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with solidity. If not, see .
-*/
-// SPDX-License-Identifier: GPL-3.0
-/**
- * Unit tests for IndentedWriter.
- */
-
-#include
-
-#include
-
-#include
-
-
-namespace solidity::util::test
-{
-
-BOOST_AUTO_TEST_SUITE(IndentedWriterTest)
-
-BOOST_AUTO_TEST_CASE(empty)
-{
- IndentedWriter iw;
- BOOST_CHECK_EQUAL(iw.format(), "\n");
-}
-
-BOOST_AUTO_TEST_CASE(new_lines)
-{
- IndentedWriter iw;
- iw.newLine();
- BOOST_CHECK_EQUAL(iw.format(), "\n");
-}
-
-BOOST_AUTO_TEST_CASE(text_without_newline)
-{
- IndentedWriter iw;
- iw.add("Hello World");
- BOOST_CHECK_EQUAL(iw.format(), "Hello World\n");
-}
-
-BOOST_AUTO_TEST_CASE(text_with_newline)
-{
- IndentedWriter iw;
- iw.addLine("Hello World");
- BOOST_CHECK_EQUAL(iw.format(), "Hello World\n\n");
-}
-
-BOOST_AUTO_TEST_CASE(indent)
-{
- IndentedWriter iw;
- iw.addLine("Hello");
- iw.indent();
- iw.addLine("World");
- iw.unindent();
- iw.addLine("and everyone else");
- BOOST_CHECK_EQUAL(iw.format(), "Hello\n World\nand everyone else\n\n");
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-}
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;
}