Avoid accidental gpui transitive dependency in collab (#2914)

Max Brunsfeld created

Release Notes:

- N/A

Change summary

Cargo.lock                                              |  2 
crates/collab/src/tests/integration_tests.rs            |  4 
crates/collab/src/tests/randomized_integration_tests.rs |  2 
crates/copilot/src/copilot.rs                           |  2 
crates/fs/Cargo.toml                                    |  1 
crates/fs/src/fs.rs                                     | 67 ----------
crates/language/src/buffer.rs                           |  1 
crates/language/src/buffer_tests.rs                     |  2 
crates/language/src/language.rs                         |  1 
crates/language/src/proto.rs                            | 12 
crates/project/src/lsp_command.rs                       |  2 
crates/project/src/project_tests.rs                     |  4 
crates/project/src/worktree.rs                          |  4 
crates/text/Cargo.toml                                  |  1 
crates/text/src/text.rs                                 | 67 ++++++++++
15 files changed, 85 insertions(+), 87 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -2768,6 +2768,7 @@ dependencies = [
  "smol",
  "sum_tree",
  "tempfile",
+ "text",
  "time 0.3.27",
  "util",
 ]
@@ -7636,7 +7637,6 @@ dependencies = [
  "ctor",
  "digest 0.9.0",
  "env_logger 0.9.3",
- "fs",
  "gpui",
  "lazy_static",
  "log",

crates/collab/src/tests/integration_tests.rs 🔗

@@ -9,7 +9,7 @@ use editor::{
     test::editor_test_context::EditorTestContext, ConfirmCodeAction, ConfirmCompletion,
     ConfirmRename, Editor, ExcerptRange, MultiBuffer, Redo, Rename, ToggleCodeActions, Undo,
 };
-use fs::{repository::GitFileStatus, FakeFs, Fs as _, LineEnding, RemoveOptions};
+use fs::{repository::GitFileStatus, FakeFs, Fs as _, RemoveOptions};
 use futures::StreamExt as _;
 use gpui::{
     executor::Deterministic, geometry::vector::vec2f, test::EmptyView, AppContext, ModelHandle,
@@ -19,7 +19,7 @@ use indoc::indoc;
 use language::{
     language_settings::{AllLanguageSettings, Formatter, InlayHintSettings},
     tree_sitter_rust, Anchor, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language,
-    LanguageConfig, OffsetRangeExt, Point, Rope,
+    LanguageConfig, LineEnding, OffsetRangeExt, Point, Rope,
 };
 use live_kit_client::MacOSDisplay;
 use lsp::LanguageServerId;

crates/copilot/src/copilot.rs 🔗

@@ -1188,7 +1188,7 @@ mod tests {
             _: u64,
             _: &clock::Global,
             _: language::RopeFingerprint,
-            _: ::fs::LineEnding,
+            _: language::LineEnding,
             _: std::time::SystemTime,
             _: &mut AppContext,
         ) {

crates/fs/Cargo.toml 🔗

@@ -12,6 +12,7 @@ collections = { path = "../collections" }
 gpui = { path = "../gpui" }
 lsp = { path = "../lsp" }
 rope = { path = "../rope" }
+text = { path = "../text" }
 util = { path = "../util" }
 sum_tree = { path = "../sum_tree" }
 rpc = { path = "../rpc" }

crates/fs/src/fs.rs 🔗

@@ -4,14 +4,10 @@ use anyhow::{anyhow, Result};
 use fsevent::EventStream;
 use futures::{future::BoxFuture, Stream, StreamExt};
 use git2::Repository as LibGitRepository;
-use lazy_static::lazy_static;
 use parking_lot::Mutex;
-use regex::Regex;
 use repository::GitRepository;
 use rope::Rope;
 use smol::io::{AsyncReadExt, AsyncWriteExt};
-use std::borrow::Cow;
-use std::cmp;
 use std::io::Write;
 use std::sync::Arc;
 use std::{
@@ -22,6 +18,7 @@ use std::{
     time::{Duration, SystemTime},
 };
 use tempfile::NamedTempFile;
+use text::LineEnding;
 use util::ResultExt;
 
 #[cfg(any(test, feature = "test-support"))]
@@ -33,66 +30,6 @@ use std::ffi::OsStr;
 #[cfg(any(test, feature = "test-support"))]
 use std::sync::Weak;
 
-lazy_static! {
-    static ref LINE_SEPARATORS_REGEX: Regex = Regex::new("\r\n|\r|\u{2028}|\u{2029}").unwrap();
-}
-
-#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum LineEnding {
-    Unix,
-    Windows,
-}
-
-impl Default for LineEnding {
-    fn default() -> Self {
-        #[cfg(unix)]
-        return Self::Unix;
-
-        #[cfg(not(unix))]
-        return Self::CRLF;
-    }
-}
-
-impl LineEnding {
-    pub fn as_str(&self) -> &'static str {
-        match self {
-            LineEnding::Unix => "\n",
-            LineEnding::Windows => "\r\n",
-        }
-    }
-
-    pub fn detect(text: &str) -> Self {
-        let mut max_ix = cmp::min(text.len(), 1000);
-        while !text.is_char_boundary(max_ix) {
-            max_ix -= 1;
-        }
-
-        if let Some(ix) = text[..max_ix].find(&['\n']) {
-            if ix > 0 && text.as_bytes()[ix - 1] == b'\r' {
-                Self::Windows
-            } else {
-                Self::Unix
-            }
-        } else {
-            Self::default()
-        }
-    }
-
-    pub fn normalize(text: &mut String) {
-        if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(text, "\n") {
-            *text = replaced;
-        }
-    }
-
-    pub fn normalize_arc(text: Arc<str>) -> Arc<str> {
-        if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(&text, "\n") {
-            replaced.into()
-        } else {
-            text
-        }
-    }
-}
-
 #[async_trait::async_trait]
 pub trait Fs: Send + Sync {
     async fn create_dir(&self, path: &Path) -> Result<()>;
@@ -520,7 +457,7 @@ impl FakeFsState {
 }
 
 #[cfg(any(test, feature = "test-support"))]
-lazy_static! {
+lazy_static::lazy_static! {
     pub static ref FS_DOT_GIT: &'static OsStr = OsStr::new(".git");
 }
 

crates/language/src/buffer.rs 🔗

@@ -15,7 +15,6 @@ use crate::{
 };
 use anyhow::{anyhow, Result};
 pub use clock::ReplicaId;
-use fs::LineEnding;
 use futures::FutureExt as _;
 use gpui::{fonts::HighlightStyle, AppContext, Entity, ModelContext, Task};
 use lsp::LanguageServerId;

crates/language/src/buffer_tests.rs 🔗

@@ -5,7 +5,6 @@ use crate::language_settings::{
 use super::*;
 use clock::ReplicaId;
 use collections::BTreeMap;
-use fs::LineEnding;
 use gpui::{AppContext, ModelHandle};
 use indoc::indoc;
 use proto::deserialize_operation;
@@ -20,6 +19,7 @@ use std::{
     time::{Duration, Instant},
 };
 use text::network::Network;
+use text::LineEnding;
 use unindent::Unindent as _;
 use util::{assert_set_eq, post_inc, test::marked_text_ranges, RandomCharIter};
 

crates/language/src/language.rs 🔗

@@ -57,6 +57,7 @@ pub use diagnostic_set::DiagnosticEntry;
 pub use lsp::LanguageServerId;
 pub use outline::{Outline, OutlineItem};
 pub use syntax_map::{OwnedSyntaxLayerInfo, SyntaxLayerInfo};
+pub use text::LineEnding;
 pub use tree_sitter::{Parser, Tree};
 
 pub fn init(cx: &mut AppContext) {

crates/language/src/proto.rs 🔗

@@ -20,17 +20,17 @@ pub fn deserialize_fingerprint(fingerprint: &str) -> Result<RopeFingerprint> {
         .map_err(|error| anyhow!("invalid fingerprint: {}", error))
 }
 
-pub fn deserialize_line_ending(message: proto::LineEnding) -> fs::LineEnding {
+pub fn deserialize_line_ending(message: proto::LineEnding) -> text::LineEnding {
     match message {
-        proto::LineEnding::Unix => fs::LineEnding::Unix,
-        proto::LineEnding::Windows => fs::LineEnding::Windows,
+        proto::LineEnding::Unix => text::LineEnding::Unix,
+        proto::LineEnding::Windows => text::LineEnding::Windows,
     }
 }
 
-pub fn serialize_line_ending(message: fs::LineEnding) -> proto::LineEnding {
+pub fn serialize_line_ending(message: text::LineEnding) -> proto::LineEnding {
     match message {
-        fs::LineEnding::Unix => proto::LineEnding::Unix,
-        fs::LineEnding::Windows => proto::LineEnding::Windows,
+        text::LineEnding::Unix => proto::LineEnding::Unix,
+        text::LineEnding::Windows => proto::LineEnding::Windows,
     }
 }
 

crates/project/src/lsp_command.rs 🔗

@@ -6,7 +6,6 @@ use crate::{
 use anyhow::{anyhow, Context, Result};
 use async_trait::async_trait;
 use client::proto::{self, PeerId};
-use fs::LineEnding;
 use futures::future;
 use gpui::{AppContext, AsyncAppContext, ModelHandle};
 use language::{
@@ -19,6 +18,7 @@ use language::{
 };
 use lsp::{DocumentHighlightKind, LanguageServer, LanguageServerId, OneOf, ServerCapabilities};
 use std::{cmp::Reverse, ops::Range, path::Path, sync::Arc};
+use text::LineEnding;
 
 pub fn lsp_formatting_options(tab_size: u32) -> lsp::FormattingOptions {
     lsp::FormattingOptions {

crates/project/src/project_tests.rs 🔗

@@ -1,11 +1,11 @@
 use crate::{search::PathMatcher, worktree::WorktreeModelHandle, Event, *};
-use fs::{FakeFs, LineEnding, RealFs};
+use fs::{FakeFs, RealFs};
 use futures::{future, StreamExt};
 use gpui::{executor::Deterministic, test::subscribe, AppContext};
 use language::{
     language_settings::{AllLanguageSettings, LanguageSettingsContent},
     tree_sitter_rust, tree_sitter_typescript, Diagnostic, FakeLspAdapter, LanguageConfig,
-    OffsetRangeExt, Point, ToPoint,
+    LineEnding, OffsetRangeExt, Point, ToPoint,
 };
 use lsp::Url;
 use parking_lot::Mutex;

crates/project/src/worktree.rs 🔗

@@ -8,7 +8,7 @@ use clock::ReplicaId;
 use collections::{HashMap, HashSet, VecDeque};
 use fs::{
     repository::{GitFileStatus, GitRepository, RepoPath},
-    Fs, LineEnding,
+    Fs,
 };
 use futures::{
     channel::{
@@ -27,7 +27,7 @@ use language::{
         deserialize_fingerprint, deserialize_version, serialize_fingerprint, serialize_line_ending,
         serialize_version,
     },
-    Buffer, DiagnosticEntry, File as _, PointUtf16, Rope, RopeFingerprint, Unclipped,
+    Buffer, DiagnosticEntry, File as _, LineEnding, PointUtf16, Rope, RopeFingerprint, Unclipped,
 };
 use lsp::LanguageServerId;
 use parking_lot::Mutex;

crates/text/Cargo.toml 🔗

@@ -14,7 +14,6 @@ test-support = ["rand"]
 [dependencies]
 clock = { path = "../clock" }
 collections = { path = "../collections" }
-fs = { path = "../fs" }
 rope = { path = "../rope" }
 sum_tree = { path = "../sum_tree" }
 util = { path = "../util" }

crates/text/src/text.rs 🔗

@@ -14,17 +14,17 @@ pub use anchor::*;
 use anyhow::{anyhow, Result};
 pub use clock::ReplicaId;
 use collections::{HashMap, HashSet};
-use fs::LineEnding;
 use locator::Locator;
 use operation_queue::OperationQueue;
 pub use patch::Patch;
 use postage::{oneshot, prelude::*};
 
+use lazy_static::lazy_static;
+use regex::Regex;
 pub use rope::*;
 pub use selection::*;
-use util::ResultExt;
-
 use std::{
+    borrow::Cow,
     cmp::{self, Ordering, Reverse},
     future::Future,
     iter::Iterator,
@@ -37,10 +37,15 @@ pub use subscription::*;
 pub use sum_tree::Bias;
 use sum_tree::{FilterCursor, SumTree, TreeMap};
 use undo_map::UndoMap;
+use util::ResultExt;
 
 #[cfg(any(test, feature = "test-support"))]
 use util::RandomCharIter;
 
+lazy_static! {
+    static ref LINE_SEPARATORS_REGEX: Regex = Regex::new("\r\n|\r|\u{2028}|\u{2029}").unwrap();
+}
+
 pub type TransactionId = clock::Local;
 
 pub struct Buffer {
@@ -2671,3 +2676,59 @@ impl FromAnchor for usize {
         snapshot.summary_for_anchor(anchor)
     }
 }
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum LineEnding {
+    Unix,
+    Windows,
+}
+
+impl Default for LineEnding {
+    fn default() -> Self {
+        #[cfg(unix)]
+        return Self::Unix;
+
+        #[cfg(not(unix))]
+        return Self::CRLF;
+    }
+}
+
+impl LineEnding {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            LineEnding::Unix => "\n",
+            LineEnding::Windows => "\r\n",
+        }
+    }
+
+    pub fn detect(text: &str) -> Self {
+        let mut max_ix = cmp::min(text.len(), 1000);
+        while !text.is_char_boundary(max_ix) {
+            max_ix -= 1;
+        }
+
+        if let Some(ix) = text[..max_ix].find(&['\n']) {
+            if ix > 0 && text.as_bytes()[ix - 1] == b'\r' {
+                Self::Windows
+            } else {
+                Self::Unix
+            }
+        } else {
+            Self::default()
+        }
+    }
+
+    pub fn normalize(text: &mut String) {
+        if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(text, "\n") {
+            *text = replaced;
+        }
+    }
+
+    pub fn normalize_arc(text: Arc<str>) -> Arc<str> {
+        if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(&text, "\n") {
+            replaced.into()
+        } else {
+            text
+        }
+    }
+}