aboutsummaryrefslogtreecommitdiffstats
path: root/liblangutil
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-11-26 19:44:25 +0800
committerGitHub <noreply@github.com>2018-11-26 19:44:25 +0800
commit0b474d52994028392402ca1e7f56b613ab365dec (patch)
tree86b2096c12771148d49fe9cb468531b7d6d1610a /liblangutil
parentbc137c2eeb6920cf33eea1ceaab49df3dfddad07 (diff)
parentaeb66905de3f65ca7a63addb6c9d05108986dbeb (diff)
downloaddexon-solidity-0b474d52994028392402ca1e7f56b613ab365dec.tar.gz
dexon-solidity-0b474d52994028392402ca1e7f56b613ab365dec.tar.zst
dexon-solidity-0b474d52994028392402ca1e7f56b613ab365dec.zip
Merge pull request #5497 from ethereum/langutil-SourceReferenceFormatter
Moving SourceReferenceFormatter into langutil namespace.
Diffstat (limited to 'liblangutil')
-rw-r--r--liblangutil/SourceReferenceFormatter.cpp129
-rw-r--r--liblangutil/SourceReferenceFormatter.h76
2 files changed, 205 insertions, 0 deletions
diff --git a/liblangutil/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp
new file mode 100644
index 00000000..58a65521
--- /dev/null
+++ b/liblangutil/SourceReferenceFormatter.cpp
@@ -0,0 +1,129 @@
+/*
+ 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/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * Formatting functions for errors referencing positions and locations in the source.
+ */
+
+#include <liblangutil/SourceReferenceFormatter.h>
+#include <liblangutil/Scanner.h>
+#include <liblangutil/Exceptions.h>
+
+using namespace std;
+using namespace dev;
+using namespace langutil;
+
+void SourceReferenceFormatter::printSourceLocation(SourceLocation const* _location)
+{
+ if (!_location || !_location->sourceName)
+ return; // Nothing we can print here
+ auto const& scanner = m_scannerFromSourceName(*_location->sourceName);
+ int startLine;
+ int startColumn;
+ tie(startLine, startColumn) = scanner.translatePositionToLineColumn(_location->start);
+ int endLine;
+ int endColumn;
+ tie(endLine, endColumn) = scanner.translatePositionToLineColumn(_location->end);
+ if (startLine == endLine)
+ {
+ string line = scanner.lineAtPosition(_location->start);
+
+ int locationLength = endColumn - startColumn;
+ if (locationLength > 150)
+ {
+ line = line.substr(0, startColumn + 35) + " ... " + line.substr(endColumn - 35);
+ endColumn = startColumn + 75;
+ locationLength = 75;
+ }
+ if (line.length() > 150)
+ {
+ int len = line.length();
+ line = line.substr(max(0, startColumn - 35), min(startColumn, 35) + min(locationLength + 35, len - startColumn));
+ if (startColumn + locationLength + 35 < len)
+ line += " ...";
+ if (startColumn > 35)
+ {
+ line = " ... " + line;
+ startColumn = 40;
+ }
+ endColumn = startColumn + locationLength;
+ }
+
+ m_stream << line << endl;
+
+ for_each(
+ line.cbegin(),
+ line.cbegin() + startColumn,
+ [this](char const& ch) { m_stream << (ch == '\t' ? '\t' : ' '); }
+ );
+ m_stream << "^";
+ if (endColumn > startColumn + 2)
+ m_stream << string(endColumn - startColumn - 2, '-');
+ if (endColumn > startColumn + 1)
+ m_stream << "^";
+ m_stream << endl;
+ }
+ else
+ m_stream <<
+ scanner.lineAtPosition(_location->start) <<
+ endl <<
+ string(startColumn, ' ') <<
+ "^ (Relevant source part starts here and spans across multiple lines)." <<
+ endl;
+}
+
+void SourceReferenceFormatter::printSourceName(SourceLocation const* _location)
+{
+ if (!_location || !_location->sourceName)
+ return; // Nothing we can print here
+ auto const& scanner = m_scannerFromSourceName(*_location->sourceName);
+ int startLine;
+ int startColumn;
+ tie(startLine, startColumn) = scanner.translatePositionToLineColumn(_location->start);
+ m_stream << *_location->sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": ";
+}
+
+void SourceReferenceFormatter::printExceptionInformation(
+ dev::Exception const& _exception,
+ string const& _name
+)
+{
+ SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
+ auto secondarylocation = boost::get_error_info<errinfo_secondarySourceLocation>(_exception);
+
+ printSourceName(location);
+
+ m_stream << _name;
+ if (string const* description = boost::get_error_info<errinfo_comment>(_exception))
+ m_stream << ": " << *description << endl;
+ else
+ m_stream << endl;
+
+ printSourceLocation(location);
+
+ if (secondarylocation && !secondarylocation->infos.empty())
+ {
+ for (auto info: secondarylocation->infos)
+ {
+ printSourceName(&info.second);
+ m_stream << info.first << endl;
+ printSourceLocation(&info.second);
+ }
+ m_stream << endl;
+ }
+}
diff --git a/liblangutil/SourceReferenceFormatter.h b/liblangutil/SourceReferenceFormatter.h
new file mode 100644
index 00000000..0ef3ca00
--- /dev/null
+++ b/liblangutil/SourceReferenceFormatter.h
@@ -0,0 +1,76 @@
+/*
+ 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/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * Formatting functions for errors referencing positions and locations in the source.
+ */
+
+#pragma once
+
+#include <ostream>
+#include <sstream>
+#include <functional>
+
+namespace dev
+{
+struct Exception; // forward
+}
+
+namespace langutil
+{
+struct SourceLocation;
+class Scanner;
+
+class SourceReferenceFormatter
+{
+public:
+ using ScannerFromSourceNameFun = std::function<langutil::Scanner const&(std::string const&)>;
+
+ explicit SourceReferenceFormatter(
+ std::ostream& _stream,
+ ScannerFromSourceNameFun _scannerFromSourceName
+ ):
+ m_stream(_stream),
+ m_scannerFromSourceName(std::move(_scannerFromSourceName))
+ {}
+
+ /// Prints source location if it is given.
+ void printSourceLocation(langutil::SourceLocation const* _location);
+ void printExceptionInformation(dev::Exception const& _exception, std::string const& _name);
+
+ static std::string formatExceptionInformation(
+ dev::Exception const& _exception,
+ std::string const& _name,
+ ScannerFromSourceNameFun const& _scannerFromSourceName
+ )
+ {
+ std::ostringstream errorOutput;
+
+ SourceReferenceFormatter formatter(errorOutput, _scannerFromSourceName);
+ formatter.printExceptionInformation(_exception, _name);
+ return errorOutput.str();
+ }
+private:
+ /// Prints source name if location is given.
+ void printSourceName(langutil::SourceLocation const* _location);
+
+ std::ostream& m_stream;
+ ScannerFromSourceNameFun m_scannerFromSourceName;
+};
+
+}