aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlaž Hrastnik2021-09-06 02:00:33 +0000
committerBlaž Hrastnik2021-09-06 02:00:33 +0000
commit57ed5180e0e1af3b3ddcb478c4a6d6ecd969cd40 (patch)
tree1a946e4bb1a406c8d5366cfee418948f1922e34e
parent08967baef62772177bba95f99990e69094735a2b (diff)
lsp: Improve line ending handling when generating TextEdit
-rw-r--r--helix-lsp/src/client.rs10
-rw-r--r--helix-view/src/document.rs34
2 files changed, 41 insertions, 3 deletions
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index fd34f45d..52b2c1c9 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -3,7 +3,7 @@ use crate::{
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 lsp_types as lsp;
use serde_json::Value;
@@ -356,7 +356,6 @@ impl Client {
//
// Calculation is therefore a bunch trickier.
- // TODO: stolen from syntax.rs, share
use helix_core::RopeSlice;
fn traverse(pos: lsp::Position, text: RopeSlice) -> lsp::Position {
let lsp::Position {
@@ -366,7 +365,12 @@ impl Client {
let mut chars = text.chars().peekable();
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;
character = 0;
} else {
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index e890a336..b2c02927 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -892,6 +892,40 @@ mod test {
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]
fn changeset_to_changes() {
use helix_lsp::{lsp, Client, OffsetEncoding};
let text = Rope::from("hello");