Simplify buffer constructor methods

Max Brunsfeld created

Don't expose the `buffer::History` to callers of `language::Buffer`

Change summary

crates/editor/src/display_map.rs | 12 +++----
crates/editor/src/lib.rs         | 29 +++++++-------------
crates/language/src/lib.rs       | 45 +++++++++++++------------------
crates/language/src/tests.rs     | 48 ++++++++++++++-------------------
crates/project/src/worktree.rs   | 18 +++---------
5 files changed, 60 insertions(+), 92 deletions(-)

Detailed changes

crates/editor/src/display_map.rs 🔗

@@ -359,7 +359,7 @@ mod tests {
     use super::*;
     use crate::{movement, test::*};
     use gpui::{color::Color, MutableAppContext};
-    use language::{History, Language, LanguageConfig, RandomCharIter, SelectionGoal};
+    use language::{Language, LanguageConfig, RandomCharIter, SelectionGoal};
     use rand::{prelude::StdRng, Rng};
     use std::{env, sync::Arc};
     use theme::SyntaxTheme;
@@ -701,9 +701,8 @@ mod tests {
         );
         lang.set_theme(&theme);
 
-        let buffer = cx.add_model(|cx| {
-            Buffer::from_history(0, History::new(text.into()), None, Some(lang), None, cx)
-        });
+        let buffer =
+            cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Some(lang), None, cx));
         buffer.condition(&cx, |buf, _| !buf.is_parsing()).await;
 
         let tab_size = 2;
@@ -789,9 +788,8 @@ mod tests {
         );
         lang.set_theme(&theme);
 
-        let buffer = cx.add_model(|cx| {
-            Buffer::from_history(0, History::new(text.into()), None, Some(lang), None, cx)
-        });
+        let buffer =
+            cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Some(lang), None, cx));
         buffer.condition(&cx, |buf, _| !buf.is_parsing()).await;
 
         let font_cache = cx.font_cache();

crates/editor/src/lib.rs 🔗

@@ -2903,7 +2903,7 @@ impl SelectionExt for Selection {
 mod tests {
     use super::*;
     use crate::test::sample_text;
-    use buffer::{History, Point};
+    use buffer::Point;
     use unindent::Unindent;
 
     #[gpui::test]
@@ -4406,10 +4406,10 @@ mod tests {
     #[gpui::test]
     async fn test_select_larger_smaller_syntax_node(mut cx: gpui::TestAppContext) {
         let settings = cx.read(EditorSettings::test);
-        let language = Arc::new(Language::new(
+        let language = Some(Arc::new(Language::new(
             LanguageConfig::default(),
             tree_sitter_rust::language(),
-        ));
+        )));
 
         let text = r#"
             use mod1::mod2::{mod3, mod4};
@@ -4420,10 +4420,7 @@ mod tests {
         "#
         .unindent();
 
-        let buffer = cx.add_model(|cx| {
-            let history = History::new(text.into());
-            Buffer::from_history(0, history, None, Some(language), None, cx)
-        });
+        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
         let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
         view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
             .await;
@@ -4550,7 +4547,7 @@ mod tests {
     #[gpui::test]
     async fn test_autoclose_pairs(mut cx: gpui::TestAppContext) {
         let settings = cx.read(EditorSettings::test);
-        let language = Arc::new(Language::new(
+        let language = Some(Arc::new(Language::new(
             LanguageConfig {
                 brackets: vec![
                     BracketPair {
@@ -4569,7 +4566,7 @@ mod tests {
                 ..Default::default()
             },
             tree_sitter_rust::language(),
-        ));
+        )));
 
         let text = r#"
             a
@@ -4579,10 +4576,7 @@ mod tests {
         "#
         .unindent();
 
-        let buffer = cx.add_model(|cx| {
-            let history = History::new(text.into());
-            Buffer::from_history(0, history, None, Some(language), None, cx)
-        });
+        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
         let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
         view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
             .await;
@@ -4665,7 +4659,7 @@ mod tests {
     #[gpui::test]
     async fn test_extra_newline_insertion(mut cx: gpui::TestAppContext) {
         let settings = cx.read(EditorSettings::test);
-        let language = Arc::new(Language::new(
+        let language = Some(Arc::new(Language::new(
             LanguageConfig {
                 brackets: vec![
                     BracketPair {
@@ -4684,7 +4678,7 @@ mod tests {
                 ..Default::default()
             },
             tree_sitter_rust::language(),
-        ));
+        )));
 
         let text = concat!(
             "{   }\n",     // Suppress rustfmt
@@ -4694,10 +4688,7 @@ mod tests {
             "{{} }\n",     //
         );
 
-        let buffer = cx.add_model(|cx| {
-            let history = History::new(text.into());
-            Buffer::from_history(0, history, None, Some(language), None, cx)
-        });
+        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
         let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
         view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
             .await;

crates/language/src/lib.rs 🔗

@@ -197,26 +197,22 @@ impl Buffer {
                 History::new(base_text.into()),
             ),
             None,
-            None,
-            None,
-            cx,
         )
     }
 
-    pub fn from_history(
+    pub fn from_file<T: Into<Arc<str>>>(
         replica_id: ReplicaId,
-        history: History,
-        file: Option<Box<dyn File>>,
-        language: Option<Arc<Language>>,
-        language_server: Option<Arc<lsp::LanguageServer>>,
+        base_text: T,
+        file: Box<dyn File>,
         cx: &mut ModelContext<Self>,
     ) -> Self {
         Self::build(
-            TextBuffer::new(replica_id, cx.model_id() as u64, history),
-            file,
-            language,
-            language_server,
-            cx,
+            TextBuffer::new(
+                replica_id,
+                cx.model_id() as u64,
+                History::new(base_text.into()),
+            ),
+            Some(file),
         )
     }
 
@@ -224,25 +220,24 @@ impl Buffer {
         replica_id: ReplicaId,
         message: proto::Buffer,
         file: Option<Box<dyn File>>,
-        language: Option<Arc<Language>>,
-        cx: &mut ModelContext<Self>,
     ) -> Result<Self> {
         Ok(Self::build(
             TextBuffer::from_proto(replica_id, message)?,
             file,
-            language,
-            None,
-            cx,
         ))
     }
 
-    fn build(
-        buffer: TextBuffer,
-        file: Option<Box<dyn File>>,
+    pub fn with_language(
+        mut self,
         language: Option<Arc<Language>>,
-        language_server: Option<Arc<lsp::LanguageServer>>,
+        language_server: Option<Arc<LanguageServer>>,
         cx: &mut ModelContext<Self>,
     ) -> Self {
+        self.set_language(language, language_server, cx);
+        self
+    }
+
+    fn build(buffer: TextBuffer, file: Option<Box<dyn File>>) -> Self {
         let saved_mtime;
         if let Some(file) = file.as_ref() {
             saved_mtime = file.mtime();
@@ -250,7 +245,7 @@ impl Buffer {
             saved_mtime = UNIX_EPOCH;
         }
 
-        let mut result = Self {
+        Self {
             text: buffer,
             saved_mtime,
             saved_version: clock::Global::new(),
@@ -266,9 +261,7 @@ impl Buffer {
             language_server: None,
             #[cfg(test)]
             operations: Default::default(),
-        };
-        result.set_language(language, language_server, cx);
-        result
+        }
     }
 
     pub fn snapshot(&self) -> Snapshot {

crates/language/src/tests.rs 🔗

@@ -78,10 +78,8 @@ async fn test_apply_diff(mut cx: gpui::TestAppContext) {
 
 #[gpui::test]
 async fn test_reparse(mut cx: gpui::TestAppContext) {
-    let buffer = cx.add_model(|cx| {
-        let text = "fn a() {}".into();
-        Buffer::from_history(0, History::new(text), None, Some(rust_lang()), None, cx)
-    });
+    let text = "fn a() {}";
+    let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(rust_lang(), None, cx));
 
     // Wait for the initial text to parse
     buffer
@@ -222,9 +220,8 @@ fn test_enclosing_bracket_ranges(cx: &mut MutableAppContext) {
                 }
             }
         "
-        .unindent()
-        .into();
-        Buffer::from_history(0, History::new(text), None, Some(rust_lang()), None, cx)
+        .unindent();
+        Buffer::new(0, text, cx).with_language(rust_lang(), None, cx)
     });
     let buffer = buffer.read(cx);
     assert_eq!(
@@ -253,9 +250,8 @@ fn test_enclosing_bracket_ranges(cx: &mut MutableAppContext) {
 #[gpui::test]
 fn test_edit_with_autoindent(cx: &mut MutableAppContext) {
     cx.add_model(|cx| {
-        let text = "fn a() {}".into();
-        let mut buffer =
-            Buffer::from_history(0, History::new(text), None, Some(rust_lang()), None, cx);
+        let text = "fn a() {}";
+        let mut buffer = Buffer::new(0, text, cx).with_language(rust_lang(), None, cx);
 
         buffer.edit_with_autoindent([8..8], "\n\n", cx);
         assert_eq!(buffer.text(), "fn a() {\n    \n}");
@@ -273,8 +269,9 @@ fn test_edit_with_autoindent(cx: &mut MutableAppContext) {
 #[gpui::test]
 fn test_autoindent_moves_selections(cx: &mut MutableAppContext) {
     cx.add_model(|cx| {
-        let text = History::new("fn a() {}".into());
-        let mut buffer = Buffer::from_history(0, text, None, Some(rust_lang()), None, cx);
+        let text = "fn a() {}";
+
+        let mut buffer = Buffer::new(0, text, cx).with_language(rust_lang(), None, cx);
 
         let selection_set_id = buffer.add_selection_set(Vec::new(), cx);
         buffer.start_transaction(Some(selection_set_id)).unwrap();
@@ -331,10 +328,9 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut Muta
             d;
             }
         "
-        .unindent()
-        .into();
-        let mut buffer =
-            Buffer::from_history(0, History::new(text), None, Some(rust_lang()), None, cx);
+        .unindent();
+
+        let mut buffer = Buffer::new(0, text, cx).with_language(rust_lang(), None, cx);
 
         // Lines 2 and 3 don't match the indentation suggestion. When editing these lines,
         // their indentation is not adjusted.
@@ -378,14 +374,12 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut Muta
 #[gpui::test]
 fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut MutableAppContext) {
     cx.add_model(|cx| {
-        let text = History::new(
-            "
-                fn a() {}
-            "
-            .unindent()
-            .into(),
-        );
-        let mut buffer = Buffer::from_history(0, text, None, Some(rust_lang()), None, cx);
+        let text = "
+            fn a() {}
+        "
+        .unindent();
+
+        let mut buffer = Buffer::new(0, text, cx).with_language(rust_lang(), None, cx);
 
         buffer.edit_with_autoindent([5..5], "\nb", cx);
         assert_eq!(
@@ -440,8 +434,8 @@ impl Buffer {
     }
 }
 
-fn rust_lang() -> Arc<Language> {
-    Arc::new(
+fn rust_lang() -> Option<Arc<Language>> {
+    Some(Arc::new(
         Language::new(
             LanguageConfig {
                 name: "Rust".to_string(),
@@ -461,7 +455,7 @@ fn rust_lang() -> Arc<Language> {
         .unwrap()
         .with_brackets_query(r#" ("{" @open "}" @close) "#)
         .unwrap(),
-    )
+    ))
 }
 
 fn empty(point: Point) -> Range<Point> {

crates/project/src/worktree.rs 🔗

@@ -12,7 +12,7 @@ use gpui::{
     executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
     Task, UpgradeModelHandle, WeakModelHandle,
 };
-use language::{Buffer, History, LanguageRegistry, Operation, Rope};
+use language::{Buffer, LanguageRegistry, Operation, Rope};
 use lazy_static::lazy_static;
 use lsp::LanguageServer;
 use parking_lot::Mutex;
@@ -892,10 +892,7 @@ impl LocalWorktree {
                         .cloned()
                 });
                 let buffer = cx.add_model(|cx| {
-                    Buffer::from_history(
-                        0,
-                        History::new(contents.into()),
-                        Some(Box::new(file)),
+                    Buffer::from_file(0, contents, Box::new(file), cx).with_language(
                         language,
                         language_server,
                         cx,
@@ -1321,14 +1318,9 @@ impl RemoteWorktree {
                 let remote_buffer = response.buffer.ok_or_else(|| anyhow!("empty buffer"))?;
                 let buffer_id = remote_buffer.id as usize;
                 let buffer = cx.add_model(|cx| {
-                    Buffer::from_proto(
-                        replica_id,
-                        remote_buffer,
-                        Some(Box::new(file)),
-                        language,
-                        cx,
-                    )
-                    .unwrap()
+                    Buffer::from_proto(replica_id, remote_buffer, Some(Box::new(file)))
+                        .unwrap()
+                        .with_language(language, None, cx)
                 });
                 this.update(&mut cx, |this, cx| {
                     let this = this.as_remote_mut().unwrap();