-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Interactive syntax test tool. #3709
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| /* | ||
| 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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <boost/noncopyable.hpp> | ||
|
|
||
| #include <ostream> | ||
| #include <vector> | ||
|
|
||
| namespace dev | ||
| { | ||
| namespace solidity | ||
| { | ||
| namespace test | ||
| { | ||
|
|
||
| namespace formatting | ||
| { | ||
|
|
||
| static constexpr char const* RESET = "\033[0m"; | ||
| static constexpr char const* RED = "\033[1;31m"; | ||
| static constexpr char const* GREEN = "\033[1;32m"; | ||
| static constexpr char const* YELLOW = "\033[1;33m"; | ||
| static constexpr char const* CYAN = "\033[1;36m"; | ||
| static constexpr char const* BOLD = "\033[1m"; | ||
| static constexpr char const* INVERSE = "\033[7m"; | ||
|
|
||
| } | ||
|
|
||
| class FormattedScope: boost::noncopyable | ||
| { | ||
| public: | ||
| /// @arg _formatting List of formatting strings (e.g. colors) defined in the formatting namespace. | ||
| FormattedScope(std::ostream& _stream, bool const _enabled, std::vector<char const*> const& _formatting): | ||
| m_stream(_stream), m_enabled(_enabled) | ||
| { | ||
| if (m_enabled) | ||
| for (auto const& format: _formatting) | ||
| m_stream << format; | ||
| } | ||
| ~FormattedScope() { if (m_enabled) m_stream << formatting::RESET; } | ||
| template<typename T> | ||
| std::ostream& operator<<(T&& _t) { return m_stream << std::forward<T>(_t); } | ||
| private: | ||
| std::ostream& m_stream; | ||
| bool m_enabled; | ||
| }; | ||
|
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
| using namespace dev; | ||
| using namespace solidity; | ||
| using namespace dev::solidity::test; | ||
| using namespace dev::solidity::test::formatting; | ||
| using namespace std; | ||
| namespace fs = boost::filesystem; | ||
| using namespace boost::unit_test; | ||
|
|
@@ -56,41 +57,70 @@ SyntaxTest::SyntaxTest(string const& _filename) | |
| m_expectations = parseExpectations(file); | ||
| } | ||
|
|
||
| bool SyntaxTest::run(ostream& _stream, string const& _indent) | ||
| bool SyntaxTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) | ||
| { | ||
| m_errorList = parseAnalyseAndReturnError(m_source, true, true, true).second; | ||
| if (!matchesExpectations(m_errorList)) | ||
| { | ||
| std::string nextIndentLevel = _indent + "\t"; | ||
| _stream << _indent << "Expected result:" << endl; | ||
| printExpected(_stream, nextIndentLevel); | ||
| _stream << _indent << "Obtained result:\n"; | ||
| printErrorList(_stream, m_errorList, nextIndentLevel); | ||
| std::string nextIndentLevel = _linePrefix + " "; | ||
| FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; | ||
| printExpected(_stream, nextIndentLevel, _formatted); | ||
| FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:\n"; | ||
| printErrorList(_stream, m_errorList, nextIndentLevel, false, false, _formatted); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| void SyntaxTest::printExpected(ostream& _stream, string const& _indent) const | ||
| void SyntaxTest::printExpected(ostream& _stream, string const& _linePrefix, bool const _formatted) const | ||
| { | ||
| if (m_expectations.empty()) | ||
| _stream << _indent << "Success" << endl; | ||
| FormattedScope(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << endl; | ||
| else | ||
| for (auto const& expectation: m_expectations) | ||
| _stream << _indent << expectation.type << ": " << expectation.message << endl; | ||
| FormattedScope(_stream, _formatted, {BOLD, expectation.type == "Warning" ? YELLOW : RED}) << | ||
| _linePrefix << expectation.type << ": " << expectation.message << endl; | ||
| } | ||
|
|
||
| void SyntaxTest::printErrorList( | ||
| ostream& _stream, | ||
| ErrorList const& _errorList, | ||
| string const& _indent | ||
| string const& _linePrefix, | ||
| bool const _ignoreWarnings, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you use enums instead? I'm fine with named bit fields, too.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure it makes sense to define an enum/bit field for this single function alone?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, because then you know what the bools mean. |
||
| bool const _lineNumbers, | ||
| bool const _formatted | ||
| ) const | ||
| { | ||
| if (_errorList.empty()) | ||
| _stream << _indent << "Success" << endl; | ||
| FormattedScope(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << endl; | ||
| else | ||
| for (auto const& error: _errorList) | ||
| _stream << _indent << error->typeName() << ": " << errorMessage(*error) << endl; | ||
| { | ||
| bool isWarning = (error->type() == Error::Type::Warning); | ||
| if (isWarning && _ignoreWarnings) continue; | ||
|
|
||
| FormattedScope scope(_stream, _formatted, {BOLD, isWarning ? YELLOW : RED}); | ||
| _stream << _linePrefix; | ||
| if (_lineNumbers) | ||
| { | ||
| int line = offsetToLineNumber( | ||
| boost::get_error_info<errinfo_sourceLocation>(*error)->start | ||
| ); | ||
| if (line >= 0) | ||
| _stream << "(" << line << "): "; | ||
| } | ||
| _stream << error->typeName() << ": " << errorMessage(*error) << endl; | ||
| } | ||
| } | ||
|
|
||
| int SyntaxTest::offsetToLineNumber(int _location) const | ||
| { | ||
| // parseAnalyseAndReturnError(...) prepends a version pragma | ||
| _location -= strlen("pragma solidity >=0.0;\n"); | ||
| if (_location < 0 || static_cast<size_t>(_location) >= m_source.size()) | ||
| return -1; | ||
| else | ||
| return 1 + std::count(m_source.begin(), m_source.begin() + _location, '\n'); | ||
| } | ||
|
|
||
| bool SyntaxTest::matchesExpectations(ErrorList const& _errorList) const | ||
|
|
@@ -196,7 +226,7 @@ int SyntaxTest::registerTests( | |
| [fullpath] | ||
| { | ||
| std::stringstream errorStream; | ||
| if (!SyntaxTest(fullpath.string()).run(errorStream, "")) | ||
| if (!SyntaxTest(fullpath.string()).run(errorStream)) | ||
| BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str()); | ||
| }, | ||
| _path.stem().string(), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment that
_formattingis supposed to be a vector of colours from theformattednamespace.