🐛 fix(text_coordinates): convert LSP UTF-16 positions
This commit is contained in:
@@ -28,6 +28,7 @@ set(SOURCES
|
||||
interpreter_test.cppm
|
||||
provider_misc_test.cppm
|
||||
provider_surface_test.cppm
|
||||
text_coordinates_test.cppm
|
||||
../../src/tree-sitter/parser.c
|
||||
../../src/tree-sitter/scanner.c)
|
||||
|
||||
@@ -56,6 +57,7 @@ target_sources(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/interpreter_test.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/provider_misc_test.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/provider_surface_test.cppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text_coordinates_test.cppm
|
||||
../../src/bridge/glaze.cppm
|
||||
../../src/bridge/spdlog.cppm
|
||||
../../src/bridge/taskflow.cppm
|
||||
|
||||
@@ -12,6 +12,7 @@ import lsp.test.provider.json_flow;
|
||||
import lsp.test.provider.json_provider_coverage;
|
||||
import lsp.test.provider.misc;
|
||||
import lsp.test.provider.surface;
|
||||
import lsp.test.provider.text_coordinates;
|
||||
import lsp.test.provider.fixtures;
|
||||
|
||||
export int Run(int argc, char** argv)
|
||||
@@ -59,6 +60,8 @@ export int Run(int argc, char** argv)
|
||||
lsp::test::provider::ProviderMiscTests::Register(runner);
|
||||
std::cout << " - Provider surface tests" << std::endl;
|
||||
lsp::test::provider::ProviderSurfaceTests::Register(runner);
|
||||
std::cout << " - Text coordinate tests" << std::endl;
|
||||
lsp::test::provider::TextCoordinatesTests::Register(runner);
|
||||
|
||||
runner.runAllTests();
|
||||
return runner.getFailedCount();
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
module;
|
||||
|
||||
export module lsp.test.provider.text_coordinates;
|
||||
|
||||
import std;
|
||||
|
||||
import lsp.protocol;
|
||||
import lsp.test.framework;
|
||||
import lsp.utils.text_coordinates;
|
||||
|
||||
export namespace lsp::test::provider
|
||||
{
|
||||
class TextCoordinatesTests
|
||||
{
|
||||
public:
|
||||
static void Register(TestRunner& runner);
|
||||
|
||||
private:
|
||||
static TestResult TestAsciiAndBmpPositions();
|
||||
static TestResult TestSupplementaryPlanePositions();
|
||||
static TestResult TestMultilineAndClampedPositions();
|
||||
static TestResult TestMalformedUtf8IsBounded();
|
||||
static TestResult TestCalculateEndPointUsesByteColumns();
|
||||
};
|
||||
}
|
||||
|
||||
namespace lsp::test::provider
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void ExpectPosition(const utils::text_coordinates::BytePosition& actual,
|
||||
protocol::uinteger offset,
|
||||
std::uint32_t row,
|
||||
std::uint32_t column)
|
||||
{
|
||||
assertEqual(offset, actual.offset, "byte offset should match");
|
||||
assertEqual(row, actual.point.row, "Tree-sitter row should match");
|
||||
assertEqual(column, actual.point.column, "Tree-sitter byte column should match");
|
||||
}
|
||||
}
|
||||
|
||||
void TextCoordinatesTests::Register(TestRunner& runner)
|
||||
{
|
||||
runner.addTest("text coordinates convert ASCII and BMP positions", TestAsciiAndBmpPositions);
|
||||
runner.addTest("text coordinates convert supplementary-plane positions", TestSupplementaryPlanePositions);
|
||||
runner.addTest("text coordinates clamp multiline positions", TestMultilineAndClampedPositions);
|
||||
runner.addTest("text coordinates bound malformed UTF-8", TestMalformedUtf8IsBounded);
|
||||
runner.addTest("text coordinates calculate byte end points", TestCalculateEndPointUsesByteColumns);
|
||||
}
|
||||
|
||||
TestResult TextCoordinatesTests::TestAsciiAndBmpPositions()
|
||||
{
|
||||
const protocol::string content = "A中Z";
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 0 }, content), 0U, 0U, 0U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 1 }, content), 1U, 0U, 1U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 2 }, content), 4U, 0U, 4U);
|
||||
assertEqual(4U, utils::text_coordinates::ToOffset({ 0, 2 }, content), "ToOffset should use the paired conversion");
|
||||
return { "", true, "ok" };
|
||||
}
|
||||
|
||||
TestResult TextCoordinatesTests::TestSupplementaryPlanePositions()
|
||||
{
|
||||
const protocol::string content = "A😀Z";
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 1 }, content), 1U, 0U, 1U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 2 }, content), 1U, 0U, 1U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 3 }, content), 5U, 0U, 5U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 4 }, content), 6U, 0U, 6U);
|
||||
return { "", true, "ok" };
|
||||
}
|
||||
|
||||
TestResult TextCoordinatesTests::TestMultilineAndClampedPositions()
|
||||
{
|
||||
const protocol::string content = "中x\n😀y";
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 1, 0 }, content), 5U, 1U, 0U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 1, 2 }, content), 9U, 1U, 4U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 1, 100 }, content), 10U, 1U, 5U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 9, 0 }, content), 10U, 1U, 5U);
|
||||
return { "", true, "ok" };
|
||||
}
|
||||
|
||||
TestResult TextCoordinatesTests::TestMalformedUtf8IsBounded()
|
||||
{
|
||||
const protocol::string content{ 'A', static_cast<char>(0xF0), static_cast<char>(0x9F), 'Z' };
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 2 }, content), 2U, 0U, 2U);
|
||||
ExpectPosition(utils::text_coordinates::ToBytePosition({ 0, 100 }, content), 4U, 0U, 4U);
|
||||
return { "", true, "ok" };
|
||||
}
|
||||
|
||||
TestResult TextCoordinatesTests::TestCalculateEndPointUsesByteColumns()
|
||||
{
|
||||
const auto end = utils::text_coordinates::CalculateEndPoint("中\n😀x", { 2U, 3U });
|
||||
assertEqual(3U, end.row, "newline should advance the Tree-sitter row");
|
||||
assertEqual(5U, end.column, "multibyte text should advance the byte column");
|
||||
return { "", true, "ok" };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user