use rlsp_yaml_parser::{LineIndex, Span};
use tower_lsp::lsp_types::{Position, Range};
#[must_use]
pub fn offset_to_lsp(offset: u32, idx: &LineIndex) -> Position {
let (line, col) = idx.line_column(offset);
Position::new(line.saturating_sub(1), col)
}
#[must_use]
pub fn span_to_lsp(span: Span, idx: &LineIndex) -> Range {
Range::new(offset_to_lsp(span.start, idx), offset_to_lsp(span.end, idx))
}
#[cfg(test)]
mod tests {
use rlsp_yaml_parser::LineIndex;
use super::*;
fn idx(source: &str) -> LineIndex {
LineIndex::new(source)
}
#[test]
fn offset_to_lsp_line_one_saturates_to_zero() {
let source = "abc\n";
let i = idx(source);
let pos = offset_to_lsp(0, &i);
assert_eq!(pos.line, 0, "line 1 (1-based) must map to line 0 (0-based)");
assert_eq!(pos.character, 0);
}
#[test]
fn offset_to_lsp_second_line_correct() {
let source = "abc\ndef\n";
let i = idx(source);
let pos = offset_to_lsp(4, &i);
assert_eq!(pos.line, 1);
assert_eq!(pos.character, 0);
}
#[test]
fn offset_to_lsp_multibyte_character_is_codepoint_count() {
let source = "日本語\n";
let i = idx(source);
let pos = offset_to_lsp(9, &i);
assert_eq!(pos.line, 0);
assert_eq!(
pos.character, 3,
"character must be 3 codepoints, not 9 bytes"
);
}
#[test]
fn span_to_lsp_maps_start_and_end() {
let source = "key: val\n";
let i = idx(source);
let range = span_to_lsp(Span { start: 0, end: 3 }, &i);
assert_eq!(range.start.line, 0);
assert_eq!(range.start.character, 0);
assert_eq!(range.end.line, 0);
assert_eq!(range.end.character, 3);
}
}