diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 63225e1159..a4c8386b13 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -1244,7 +1244,7 @@ async fn test_buffer_reloading(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont .insert_tree( "/dir", json!({ - "a.txt": "a-contents", + "a.txt": "a\nb\nc", }), ) .await; @@ -1259,23 +1259,25 @@ async fn test_buffer_reloading(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont buffer_b.read_with(cx_b, |buf, _| { assert!(!buf.is_dirty()); assert!(!buf.has_conflict()); + assert_eq!(buf.line_ending(), LineEnding::Unix); }); + let new_contents = Rope::from("d\ne\nf"); client_a .fs - .save( - "/dir/a.txt".as_ref(), - &"new contents".into(), - LineEnding::Unix, - ) + .save("/dir/a.txt".as_ref(), &new_contents, LineEnding::Windows) .await .unwrap(); buffer_b .condition(&cx_b, |buf, _| { - buf.text() == "new contents" && !buf.is_dirty() + buf.text() == new_contents.to_string() && !buf.is_dirty() }) .await; - buffer_b.read_with(cx_b, |buf, _| assert!(!buf.has_conflict())); + buffer_b.read_with(cx_b, |buf, _| { + assert!(!buf.is_dirty()); + assert!(!buf.has_conflict()); + assert_eq!(buf.line_ending(), LineEnding::Windows); + }); } #[gpui::test(iterations = 10)] diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 5f0cc1234a..4d50affdd5 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -221,6 +221,7 @@ pub trait LocalFile: File { buffer_id: u64, version: &clock::Global, fingerprint: String, + line_ending: LineEnding, mtime: SystemTime, cx: &mut MutableAppContext, ); @@ -562,6 +563,7 @@ impl Buffer { this.did_reload( this.version(), this.as_rope().fingerprint(), + this.line_ending, new_mtime, cx, ); @@ -580,17 +582,20 @@ impl Buffer { &mut self, version: clock::Global, fingerprint: String, + line_ending: LineEnding, mtime: SystemTime, cx: &mut ModelContext, ) { self.saved_version = version; self.saved_version_fingerprint = fingerprint; + self.line_ending = line_ending; self.saved_mtime = mtime; if let Some(file) = self.file.as_ref().and_then(|f| f.as_local()) { file.buffer_reloaded( self.remote_id(), &self.saved_version, self.saved_version_fingerprint.clone(), + self.line_ending, self.saved_mtime, cx, ); @@ -2538,7 +2543,7 @@ impl std::ops::SubAssign for IndentSize { } impl LineEnding { - fn from_proto(style: proto::LineEnding) -> Self { + pub fn from_proto(style: proto::LineEnding) -> Self { match style { proto::LineEnding::Unix => Self::Unix, proto::LineEnding::Windows => Self::Windows, @@ -2565,7 +2570,7 @@ impl LineEnding { } } - fn to_proto(self) -> proto::LineEnding { + pub fn to_proto(self) -> proto::LineEnding { match self { LineEnding::Unix => proto::LineEnding::Unix, LineEnding::Windows => proto::LineEnding::Windows, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 6095ababf4..44561e6931 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -23,8 +23,9 @@ use language::{ proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CharKind, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, - Language, LanguageRegistry, LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt, - Operation, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, + Language, LanguageRegistry, LanguageServerName, LineEnding, LocalFile, LspAdapter, + OffsetRangeExt, Operation, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, + Transaction, }; use lsp::{ DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer, LanguageString, @@ -5539,8 +5540,12 @@ impl Project { _: Arc, mut cx: AsyncAppContext, ) -> Result<()> { - let payload = envelope.payload.clone(); + let payload = envelope.payload; let version = deserialize_version(payload.version); + let line_ending = LineEnding::from_proto( + proto::LineEnding::from_i32(payload.line_ending) + .ok_or_else(|| anyhow!("missing line ending"))?, + ); let mtime = payload .mtime .ok_or_else(|| anyhow!("missing mtime"))? @@ -5552,7 +5557,7 @@ impl Project { .and_then(|buffer| buffer.upgrade(cx)); if let Some(buffer) = buffer { buffer.update(cx, |buffer, cx| { - buffer.did_reload(version, payload.fingerprint, mtime, cx); + buffer.did_reload(version, payload.fingerprint, line_ending, mtime, cx); }); } Ok(()) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 77dcb064c0..2603b2b709 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1736,6 +1736,7 @@ impl language::LocalFile for File { buffer_id: u64, version: &clock::Global, fingerprint: String, + line_ending: LineEnding, mtime: SystemTime, cx: &mut MutableAppContext, ) { @@ -1749,6 +1750,7 @@ impl language::LocalFile for File { version: serialize_version(&version), mtime: Some(mtime.into()), fingerprint, + line_ending: line_ending.to_proto() as i32, }) .log_err(); } diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 9269e3bc94..6610ad41a1 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -390,6 +390,7 @@ message BufferReloaded { repeated VectorClockEntry version = 3; Timestamp mtime = 4; string fingerprint = 5; + LineEnding line_ending = 6; } message ReloadBuffers {