lsp: Improve line ending handling when generating TextEdit

This commit is contained in:
Blaž Hrastnik 2021-09-06 11:00:33 +09:00
parent 08967baef6
commit 57ed5180e0
2 changed files with 41 additions and 3 deletions

View File

@ -3,7 +3,7 @@
Call, Error, OffsetEncoding, Result, Call, Error, OffsetEncoding, Result,
}; };
use helix_core::{chars::char_is_line_ending, find_root, ChangeSet, Rope}; use helix_core::{find_root, ChangeSet, Rope};
use jsonrpc_core as jsonrpc; use jsonrpc_core as jsonrpc;
use lsp_types as lsp; use lsp_types as lsp;
use serde_json::Value; use serde_json::Value;
@ -356,7 +356,6 @@ pub fn changeset_to_changes(
// //
// Calculation is therefore a bunch trickier. // Calculation is therefore a bunch trickier.
// TODO: stolen from syntax.rs, share
use helix_core::RopeSlice; use helix_core::RopeSlice;
fn traverse(pos: lsp::Position, text: RopeSlice) -> lsp::Position { fn traverse(pos: lsp::Position, text: RopeSlice) -> lsp::Position {
let lsp::Position { let lsp::Position {
@ -366,7 +365,12 @@ fn traverse(pos: lsp::Position, text: RopeSlice) -> lsp::Position {
let mut chars = text.chars().peekable(); let mut chars = text.chars().peekable();
while let Some(ch) = chars.next() { while let Some(ch) = chars.next() {
if char_is_line_ending(ch) && !(ch == '\r' && chars.peek() == Some(&'\n')) { // LSP only considers \n, \r or \r\n as line endings
if ch == '\n' || ch == '\r' {
// consume a \r\n
if chars.peek() == Some(&'\n') {
chars.next();
}
line += 1; line += 1;
character = 0; character = 0;
} else { } else {

View File

@ -891,6 +891,40 @@ fn default() -> Self {
mod test { mod test {
use super::*; use super::*;
#[test]
fn changeset_to_changes_ignore_line_endings() {
use helix_lsp::{lsp, Client, OffsetEncoding};
let text = Rope::from("hello\r\nworld");
let mut doc = Document::from(text, None);
let view = ViewId::default();
doc.set_selection(view, Selection::single(0, 0));
let transaction =
Transaction::change(doc.text(), vec![(5, 7, Some("\n".into()))].into_iter());
let old_doc = doc.text().clone();
doc.apply(&transaction, view);
let changes = Client::changeset_to_changes(
&old_doc,
doc.text(),
transaction.changes(),
OffsetEncoding::Utf8,
);
assert_eq!(doc.text(), "hello\nworld");
assert_eq!(
changes,
&[lsp::TextDocumentContentChangeEvent {
range: Some(lsp::Range::new(
lsp::Position::new(0, 5),
lsp::Position::new(1, 0)
)),
text: "\n".into(),
range_length: None,
}]
);
}
#[test] #[test]
fn changeset_to_changes() { fn changeset_to_changes() {
use helix_lsp::{lsp, Client, OffsetEncoding}; use helix_lsp::{lsp, Client, OffsetEncoding};