🐛 fix(core): convert diagnostics to UTF-16 positions
This commit is contained in:
@@ -16,6 +16,7 @@ import lsp.manager.manager_hub;
|
|||||||
import lsp.protocol;
|
import lsp.protocol;
|
||||||
import lsp.provider.manifest;
|
import lsp.provider.manifest;
|
||||||
import lsp.scheduler.async_executor;
|
import lsp.scheduler.async_executor;
|
||||||
|
import lsp.utils.text_coordinates;
|
||||||
|
|
||||||
namespace transform = lsp::codec;
|
namespace transform = lsp::codec;
|
||||||
|
|
||||||
@@ -753,10 +754,10 @@ namespace lsp::core
|
|||||||
for (const auto& error : errors)
|
for (const auto& error : errors)
|
||||||
{
|
{
|
||||||
protocol::Diagnostic diagnostic;
|
protocol::Diagnostic diagnostic;
|
||||||
diagnostic.range.start.line = error.location.start_line;
|
diagnostic.range.start = utils::text_coordinates::ToPosition(
|
||||||
diagnostic.range.start.character = error.location.start_column;
|
TSPoint{ error.location.start_line, error.location.start_column }, content);
|
||||||
diagnostic.range.end.line = error.location.end_line;
|
diagnostic.range.end = utils::text_coordinates::ToPosition(
|
||||||
diagnostic.range.end.character = error.location.end_column;
|
TSPoint{ error.location.end_line, error.location.end_column }, content);
|
||||||
|
|
||||||
switch (error.severity)
|
switch (error.severity)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export namespace lsp::utils::text_coordinates
|
|||||||
};
|
};
|
||||||
|
|
||||||
BytePosition ToBytePosition(const protocol::Position& position, const protocol::string& content);
|
BytePosition ToBytePosition(const protocol::Position& position, const protocol::string& content);
|
||||||
|
protocol::Position ToPosition(TSPoint point, const protocol::string& content);
|
||||||
protocol::uinteger ToOffset(const protocol::Position& position, const protocol::string& content);
|
protocol::uinteger ToOffset(const protocol::Position& position, const protocol::string& content);
|
||||||
TSPoint CalculateEndPoint(const protocol::string& text, TSPoint start);
|
TSPoint CalculateEndPoint(const protocol::string& text, TSPoint start);
|
||||||
}
|
}
|
||||||
@@ -120,6 +121,37 @@ namespace lsp::utils::text_coordinates
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol::Position ToPosition(TSPoint point, const protocol::string& content)
|
||||||
|
{
|
||||||
|
std::size_t offset = 0;
|
||||||
|
std::uint32_t row = 0;
|
||||||
|
|
||||||
|
while (offset < content.size() && row < point.row)
|
||||||
|
{
|
||||||
|
if (content[offset++] == '\n')
|
||||||
|
++row;
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol::uinteger utf16_units = 0;
|
||||||
|
std::size_t byte_column = 0;
|
||||||
|
while (offset < content.size() && content[offset] != '\n' &&
|
||||||
|
byte_column < point.column)
|
||||||
|
{
|
||||||
|
const auto decoded = DecodeCharacter(content, offset);
|
||||||
|
if (decoded.byte_count > point.column - byte_column)
|
||||||
|
break;
|
||||||
|
|
||||||
|
offset += decoded.byte_count;
|
||||||
|
byte_column += decoded.byte_count;
|
||||||
|
utf16_units += decoded.utf16_units;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
.line = row,
|
||||||
|
.character = utf16_units,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protocol::uinteger ToOffset(const protocol::Position& position, const protocol::string& content)
|
protocol::uinteger ToOffset(const protocol::Position& position, const protocol::string& content)
|
||||||
{
|
{
|
||||||
return ToBytePosition(position, content).offset;
|
return ToBytePosition(position, content).offset;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export namespace lsp::test::provider
|
|||||||
static TestResult TestMultilineAndClampedPositions();
|
static TestResult TestMultilineAndClampedPositions();
|
||||||
static TestResult TestMalformedUtf8IsBounded();
|
static TestResult TestMalformedUtf8IsBounded();
|
||||||
static TestResult TestCalculateEndPointUsesByteColumns();
|
static TestResult TestCalculateEndPointUsesByteColumns();
|
||||||
|
static TestResult TestBytePointsToUtf16Positions();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +38,14 @@ namespace lsp::test::provider
|
|||||||
assertEqual(row, actual.point.row, "Tree-sitter row should match");
|
assertEqual(row, actual.point.row, "Tree-sitter row should match");
|
||||||
assertEqual(column, actual.point.column, "Tree-sitter byte column should match");
|
assertEqual(column, actual.point.column, "Tree-sitter byte column should match");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExpectLspPosition(const protocol::Position& actual,
|
||||||
|
protocol::uinteger line,
|
||||||
|
protocol::uinteger character)
|
||||||
|
{
|
||||||
|
assertEqual(line, actual.line, "LSP line should match");
|
||||||
|
assertEqual(character, actual.character, "LSP UTF-16 character should match");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextCoordinatesTests::Register(TestRunner& runner)
|
void TextCoordinatesTests::Register(TestRunner& runner)
|
||||||
@@ -46,6 +55,7 @@ namespace lsp::test::provider
|
|||||||
runner.addTest("text coordinates clamp multiline positions", TestMultilineAndClampedPositions);
|
runner.addTest("text coordinates clamp multiline positions", TestMultilineAndClampedPositions);
|
||||||
runner.addTest("text coordinates bound malformed UTF-8", TestMalformedUtf8IsBounded);
|
runner.addTest("text coordinates bound malformed UTF-8", TestMalformedUtf8IsBounded);
|
||||||
runner.addTest("text coordinates calculate byte end points", TestCalculateEndPointUsesByteColumns);
|
runner.addTest("text coordinates calculate byte end points", TestCalculateEndPointUsesByteColumns);
|
||||||
|
runner.addTest("text coordinates convert byte points to UTF-16 positions", TestBytePointsToUtf16Positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult TextCoordinatesTests::TestAsciiAndBmpPositions()
|
TestResult TextCoordinatesTests::TestAsciiAndBmpPositions()
|
||||||
@@ -93,4 +103,16 @@ namespace lsp::test::provider
|
|||||||
assertEqual(5U, end.column, "multibyte text should advance the byte column");
|
assertEqual(5U, end.column, "multibyte text should advance the byte column");
|
||||||
return { "", true, "ok" };
|
return { "", true, "ok" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestResult TextCoordinatesTests::TestBytePointsToUtf16Positions()
|
||||||
|
{
|
||||||
|
const protocol::string content = "A中😀Z\n😀x";
|
||||||
|
|
||||||
|
ExpectLspPosition(utils::text_coordinates::ToPosition({ 0U, 0U }, content), 0U, 0U);
|
||||||
|
ExpectLspPosition(utils::text_coordinates::ToPosition({ 0U, 4U }, content), 0U, 2U);
|
||||||
|
ExpectLspPosition(utils::text_coordinates::ToPosition({ 0U, 8U }, content), 0U, 4U);
|
||||||
|
ExpectLspPosition(utils::text_coordinates::ToPosition({ 1U, 4U }, content), 1U, 2U);
|
||||||
|
ExpectLspPosition(utils::text_coordinates::ToPosition({ 0U, 6U }, content), 0U, 2U);
|
||||||
|
return { "", true, "ok" };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user