diff options
author | Blaž Hrastnik | 2021-09-06 02:00:33 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2021-09-06 02:00:33 +0000 |
commit | 57ed5180e0e1af3b3ddcb478c4a6d6ecd969cd40 (patch) | |
tree | 1a946e4bb1a406c8d5366cfee418948f1922e34e | |
parent | 08967baef62772177bba95f99990e69094735a2b (diff) |
lsp: Improve line ending handling when generating TextEdit
-rw-r--r-- | helix-lsp/src/client.rs | 10 | ||||
-rw-r--r-- | helix-view/src/document.rs | 34 |
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"); |