Make language settings accessors take an arc dyn file

Max Brunsfeld created

Change summary

crates/copilot/src/copilot.rs               |  2 
crates/copilot_button/src/copilot_button.rs |  2 
crates/editor/src/editor.rs                 |  5 +--
crates/editor/src/multi_buffer.rs           |  4 +-
crates/language/src/buffer.rs               |  8 +----
crates/language/src/language_settings.rs    |  4 +-
crates/project/src/lsp_command.rs           |  3 -
crates/project/src/project.rs               | 30 +++++++++-------------
crates/project/src/project_tests.rs         | 20 +++++++++------
crates/project/src/worktree.rs              | 17 +++---------
10 files changed, 41 insertions(+), 54 deletions(-)

Detailed changes

crates/copilot/src/copilot.rs 🔗

@@ -787,7 +787,7 @@ impl Copilot {
         let position = position.to_point_utf16(buffer);
         let settings = language_settings(
             buffer.language_at(position).map(|l| l.name()).as_deref(),
-            buffer.file().map(|f| f.as_ref()),
+            buffer.file(),
             cx,
         );
         let tab_size = settings.tab_size;

crates/copilot_button/src/copilot_button.rs 🔗

@@ -285,7 +285,7 @@ impl CopilotButton {
         let file = snapshot.file_at(suggestion_anchor).cloned();
 
         self.editor_enabled = Some(
-            all_language_settings(self.file.as_ref().map(|f| f.as_ref()), cx).copilot_enabled(
+            all_language_settings(self.file.as_ref(), cx).copilot_enabled(
                 language_name.as_deref(),
                 file.as_ref().map(|file| file.path().as_ref()),
             ),

crates/editor/src/editor.rs 🔗

@@ -3211,7 +3211,7 @@ impl Editor {
         let language_name = snapshot
             .language_at(location)
             .map(|language| language.name());
-        let settings = all_language_settings(file.map(|f| f.as_ref() as _), cx);
+        let settings = all_language_settings(file, cx);
         settings.copilot_enabled(language_name.as_deref(), file.map(|f| f.path().as_ref()))
     }
 
@@ -7093,8 +7093,7 @@ impl Editor {
             .get("vim_mode")
             == Some(&serde_json::Value::Bool(true));
         let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
-        let copilot_enabled =
-            all_language_settings(file.map(|f| f.as_ref()), cx).copilot_enabled(None, None);
+        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
         let copilot_enabled_for_language = self
             .buffer
             .read(cx)

crates/editor/src/multi_buffer.rs 🔗

@@ -1382,7 +1382,7 @@ impl MultiBuffer {
         if let Some((buffer, offset)) = self.point_to_buffer_offset(point, cx) {
             let buffer = buffer.read(cx);
             language = buffer.language_at(offset).map(|l| l.name());
-            file = buffer.file().map(|f| f.as_ref());
+            file = buffer.file();
         }
         language_settings(language.as_deref(), file, cx)
     }
@@ -2795,7 +2795,7 @@ impl MultiBufferSnapshot {
         let mut file = None;
         if let Some((buffer, offset)) = self.point_to_buffer_offset(point) {
             language = buffer.language_at(offset).map(|l| l.name());
-            file = buffer.file().map(|f| f.as_ref());
+            file = buffer.file();
         }
         language_settings(language.as_deref(), file, cx)
     }

crates/language/src/buffer.rs 🔗

@@ -1808,11 +1808,7 @@ impl BufferSnapshot {
 
     pub fn language_indent_size_at<T: ToOffset>(&self, position: T, cx: &AppContext) -> IndentSize {
         let language_name = self.language_at(position).map(|language| language.name());
-        let settings = language_settings(
-            language_name.as_deref(),
-            self.file().map(|f| f.as_ref()),
-            cx,
-        );
+        let settings = language_settings(language_name.as_deref(), self.file(), cx);
         if settings.hard_tabs {
             IndentSize::tab()
         } else {
@@ -2139,7 +2135,7 @@ impl BufferSnapshot {
         let language = self.language_at(position);
         language_settings(
             language.map(|l| l.name()).as_deref(),
-            self.file.as_ref().map(AsRef::as_ref),
+            self.file.as_ref(),
             cx,
         )
     }

crates/language/src/language_settings.rs 🔗

@@ -16,7 +16,7 @@ pub fn init(cx: &mut AppContext) {
 
 pub fn language_settings<'a>(
     language: Option<&str>,
-    file: Option<&dyn File>,
+    file: Option<&Arc<dyn File>>,
     cx: &'a AppContext,
 ) -> &'a LanguageSettings {
     settings::get_local::<AllLanguageSettings>(
@@ -27,7 +27,7 @@ pub fn language_settings<'a>(
 }
 
 pub fn all_language_settings<'a>(
-    file: Option<&dyn File>,
+    file: Option<&Arc<dyn File>>,
     cx: &'a AppContext,
 ) -> &'a AllLanguageSettings {
     settings::get_local::<AllLanguageSettings>(

crates/project/src/lsp_command.rs 🔗

@@ -1717,8 +1717,7 @@ impl LspCommand for OnTypeFormatting {
 
         let tab_size = buffer.read_with(&cx, |buffer, cx| {
             let language_name = buffer.language().map(|language| language.name());
-            let file = buffer.file().map(|f| f.as_ref());
-            language_settings(language_name.as_deref(), file, cx).tab_size
+            language_settings(language_name.as_deref(), buffer.file(), cx).tab_size
         });
 
         Ok(Self {

crates/project/src/project.rs 🔗

@@ -693,12 +693,14 @@ impl Project {
         for buffer in self.opened_buffers.values() {
             if let Some(buffer) = buffer.upgrade(cx) {
                 let buffer = buffer.read(cx);
-                if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language())
-                {
+                if let Some((file, language)) = buffer.file().zip(buffer.language()) {
                     let settings =
                         language_settings(Some(language.name().as_ref()), Some(file), cx);
                     if settings.enable_language_server {
-                        language_servers_to_start.push((file.worktree.clone(), language.clone()));
+                        if let Some(file) = File::from_dyn(Some(file)) {
+                            language_servers_to_start
+                                .push((file.worktree.clone(), language.clone()));
+                        }
                     }
                 }
             }
@@ -714,10 +716,10 @@ impl Project {
             });
             if let Some(language) = language {
                 let worktree = self.worktree_for_id(*worktree_id, cx);
-                let file = worktree.and_then(|tree| tree.update(cx, |tree, cx| tree.root_file(cx)));
-                // let settings =
-                //     language_settings(Some(language.name().as_ref()), Some(file), cx);
-                if !language_settings(Some(&language.name()), file.as_ref().map(|f| f as _), cx)
+                let file = worktree.and_then(|tree| {
+                    tree.update(cx, |tree, cx| tree.root_file(cx).map(|f| f as _))
+                });
+                if !language_settings(Some(&language.name()), file.as_ref(), cx)
                     .enable_language_server
                 {
                     language_servers_to_stop.push((*worktree_id, started_lsp_name.clone()));
@@ -2362,8 +2364,8 @@ impl Project {
             Some(&language.name()),
             worktree
                 .update(cx, |tree, cx| tree.root_file(cx))
-                .as_ref()
-                .map(|f| f as _),
+                .map(|f| f as _)
+                .as_ref(),
             cx,
         )
         .enable_language_server
@@ -3464,12 +3466,7 @@ impl Project {
                 for (buffer, buffer_abs_path, language_server) in &buffers_with_paths_and_servers {
                     let settings = buffer.read_with(&cx, |buffer, cx| {
                         let language_name = buffer.language().map(|language| language.name());
-                        language_settings(
-                            language_name.as_deref(),
-                            buffer.file().map(|f| f.as_ref()),
-                            cx,
-                        )
-                        .clone()
+                        language_settings(language_name.as_deref(), buffer.file(), cx).clone()
                     });
 
                     let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save;
@@ -4481,10 +4478,9 @@ impl Project {
         let (position, tab_size) = buffer.read_with(cx, |buffer, cx| {
             let position = position.to_point_utf16(buffer);
             let language_name = buffer.language_at(position).map(|l| l.name());
-            let file = buffer.file().map(|f| f.as_ref());
             (
                 position,
-                language_settings(language_name.as_deref(), file, cx).tab_size,
+                language_settings(language_name.as_deref(), buffer.file(), cx).tab_size,
             )
         });
         self.request_lsp(

crates/project/src/project_tests.rs 🔗

@@ -99,18 +99,22 @@ async fn test_managing_project_specific_settings(
 
         let settings_a = language_settings(
             None,
-            Some(&File::for_entry(
-                tree.entry_for_path("a/a.rs").unwrap().clone(),
-                worktree.clone(),
-            )),
+            Some(
+                &(File::for_entry(
+                    tree.entry_for_path("a/a.rs").unwrap().clone(),
+                    worktree.clone(),
+                ) as _),
+            ),
             cx,
         );
         let settings_b = language_settings(
             None,
-            Some(&File::for_entry(
-                tree.entry_for_path("b/b.rs").unwrap().clone(),
-                worktree.clone(),
-            )),
+            Some(
+                &(File::for_entry(
+                    tree.entry_for_path("b/b.rs").unwrap().clone(),
+                    worktree.clone(),
+                ) as _),
+            ),
             cx,
         );
 

crates/project/src/worktree.rs 🔗

@@ -678,16 +678,9 @@ impl Worktree {
         }
     }
 
-    pub fn root_file(&self, cx: &mut ModelContext<Self>) -> Option<File> {
+    pub fn root_file(&self, cx: &mut ModelContext<Self>) -> Option<Arc<File>> {
         let entry = self.root_entry()?;
-        Some(File {
-            worktree: cx.handle(),
-            path: entry.path.clone(),
-            mtime: entry.mtime,
-            entry_id: entry.id,
-            is_local: self.is_local(),
-            is_deleted: false,
-        })
+        Some(File::for_entry(entry.clone(), cx.handle()))
     }
 }
 
@@ -2463,15 +2456,15 @@ impl language::LocalFile for File {
 }
 
 impl File {
-    pub fn for_entry(entry: Entry, worktree: ModelHandle<Worktree>) -> Self {
-        Self {
+    pub fn for_entry(entry: Entry, worktree: ModelHandle<Worktree>) -> Arc<Self> {
+        Arc::new(Self {
             worktree,
             path: entry.path.clone(),
             mtime: entry.mtime,
             entry_id: entry.id,
             is_local: true,
             is_deleted: false,
-        }
+        })
     }
 
     pub fn from_proto(