Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions liblangutil/CharStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,32 @@ string CharStream::singleLineSnippet(string const& _sourceCode, SourceLocation c

return cut;
}

optional<int> CharStream::translateLineColumnToPosition(LineColumn const& _lineColumn) const
{
return translateLineColumnToPosition(m_source, _lineColumn);
}

optional<int> CharStream::translateLineColumnToPosition(std::string const& _text, LineColumn const& _input)
{
if (_input.line < 0)
return nullopt;

size_t offset = 0;
for (int i = 0; i < _input.line; i++)
{
offset = _text.find('\n', offset);
if (offset == _text.npos)
return nullopt;
offset++; // Skip linefeed.
}

size_t endOfLine = _text.find('\n', offset);
if (endOfLine == string::npos)
endOfLine = _text.size();

if (offset + static_cast<size_t>(_input.column) > endOfLine)
return nullopt;
return offset + static_cast<size_t>(_input.column);
}

7 changes: 7 additions & 0 deletions liblangutil/CharStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#pragma once

#include <cstdint>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
Expand Down Expand Up @@ -101,6 +102,12 @@ class CharStream
LineColumn translatePositionToLineColumn(int _position) const;
///@}

/// Translates a line:column to the absolute position.
std::optional<int> translateLineColumnToPosition(LineColumn const& _lineColumn) const;

/// Translates a line:column to the absolute position for the given input text.
static std::optional<int> translateLineColumnToPosition(std::string const& _text, LineColumn const& _input);

/// Tests whether or not given octet sequence is present at the current position in stream.
/// @returns true if the sequence could be found, false otherwise.
bool prefixMatch(std::string_view _sequence)
Expand Down
85 changes: 84 additions & 1 deletion test/liblangutil/CharStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,33 @@

#include <boost/test/unit_test.hpp>

using namespace std;
using namespace solidity::test;

namespace boost::test_tools::tt_detail
{

template<>
struct print_log_value<std::optional<int>>
{
void operator()(std::ostream& _out, std::optional<int> const& _value) const
{
_out << (_value ? to_string(*_value) : "[nullopt]");
}
};

template<>
struct print_log_value<nullopt_t>
{
void operator()(std::ostream& _out, nullopt_t const&) const
{
_out << "[nullopt]";
}
};

} // namespace boost::test_tools::tt_detail


namespace solidity::langutil::test
{

Expand All @@ -48,6 +75,62 @@ BOOST_AUTO_TEST_CASE(test_fail)
);
}

namespace
{
std::optional<int> toPosition(int _line, int _column, string const& _text)
{
return CharStream{_text, "source"}.translateLineColumnToPosition(
LineColumn{_line, _column}
);
}

}

BOOST_AUTO_TEST_CASE(translateLineColumnToPosition)
{
BOOST_CHECK_EQUAL(toPosition(-1, 0, "ABC"), nullopt);
BOOST_CHECK_EQUAL(toPosition(0, -1, "ABC"), nullopt);

BOOST_CHECK_EQUAL(toPosition(0, 0, ""), 0);
BOOST_CHECK_EQUAL(toPosition(1, 0, ""), nullopt);
BOOST_CHECK_EQUAL(toPosition(0, 1, ""), nullopt);

// With last line containing no LF
BOOST_CHECK_EQUAL(toPosition(0, 0, "ABC"), 0);
BOOST_CHECK_EQUAL(toPosition(0, 1, "ABC"), 1);
BOOST_CHECK_EQUAL(toPosition(0, 2, "ABC"), 2);
BOOST_CHECK_EQUAL(toPosition(0, 3, "ABC"), 3);
BOOST_CHECK_EQUAL(toPosition(0, 4, "ABC"), nullopt);
BOOST_CHECK_EQUAL(toPosition(1, 0, "ABC"), nullopt);

BOOST_CHECK_EQUAL(toPosition(0, 3, "ABC\nDEF"), 3);
BOOST_CHECK_EQUAL(toPosition(0, 4, "ABC\nDEF"), nullopt);
BOOST_CHECK_EQUAL(toPosition(1, 0, "ABC\nDEF"), 4);
BOOST_CHECK_EQUAL(toPosition(1, 1, "ABC\nDEF"), 5);
BOOST_CHECK_EQUAL(toPosition(1, 2, "ABC\nDEF"), 6);
BOOST_CHECK_EQUAL(toPosition(1, 3, "ABC\nDEF"), 7);
BOOST_CHECK_EQUAL(toPosition(1, 4, "ABC\nDEF"), nullopt);
BOOST_CHECK_EQUAL(toPosition(2, 0, "ABC\nDEF"), nullopt);
BOOST_CHECK_EQUAL(toPosition(2, 1, "ABC\nDEF"), nullopt);

// With last line containing LF
BOOST_CHECK_EQUAL(toPosition(0, 0, "ABC\nDEF\n"), 0);
BOOST_CHECK_EQUAL(toPosition(0, 1, "ABC\nDEF\n"), 1);
BOOST_CHECK_EQUAL(toPosition(0, 2, "ABC\nDEF\n"), 2);

BOOST_CHECK_EQUAL(toPosition(1, 0, "ABC\nDEF\n"), 4);
BOOST_CHECK_EQUAL(toPosition(1, 1, "ABC\nDEF\n"), 5);
BOOST_CHECK_EQUAL(toPosition(1, 2, "ABC\nDEF\n"), 6);
BOOST_CHECK_EQUAL(toPosition(1, 3, "ABC\nDEF\n"), 7);
BOOST_CHECK_EQUAL(toPosition(1, 4, "ABC\nDEF\n"), nullopt);
BOOST_CHECK_EQUAL(toPosition(2, 0, "ABC\nDEF\n"), 8);
BOOST_CHECK_EQUAL(toPosition(2, 1, "ABC\nDEF\n"), nullopt);

BOOST_CHECK_EQUAL(toPosition(2, 0, "ABC\nDEF\nGHI\n"), 8);
BOOST_CHECK_EQUAL(toPosition(2, 1, "ABC\nDEF\nGHI\n"), 9);
BOOST_CHECK_EQUAL(toPosition(2, 2, "ABC\nDEF\nGHI\n"), 10);
}

BOOST_AUTO_TEST_SUITE_END()

} // end namespaces
}