From a2ab7c9eb95f4970b0c2222e4494c83e2cb2779b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 31 May 2023 14:42:15 -0700 Subject: [PATCH] Respect project-specific settings for copilot --- crates/copilot/src/copilot.rs | 2 +- crates/copilot_button/src/copilot_button.rs | 32 +++++++++++-------- crates/editor/src/editor.rs | 15 +++++---- crates/language/src/language_settings.rs | 10 ++++-- crates/project/src/project.rs | 35 +++++++++++---------- crates/project/src/worktree.rs | 2 +- 6 files changed, 56 insertions(+), 40 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 88b0aebd17..1084222648 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -318,7 +318,7 @@ impl Copilot { fn enable_or_disable_copilot(&mut self, cx: &mut ModelContext) { let http = self.http.clone(); let node_runtime = self.node_runtime.clone(); - if all_language_settings(cx).copilot_enabled(None, None) { + if all_language_settings(None, cx).copilot_enabled(None, None) { if matches!(self.server, CopilotServer::Disabled) { let start_task = cx .spawn({ diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index 686b3d2dfb..4cb7c15bd9 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -9,7 +9,10 @@ use gpui::{ AnyElement, AppContext, AsyncAppContext, Element, Entity, MouseState, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext, }; -use language::language_settings::{self, all_language_settings, AllLanguageSettings}; +use language::{ + language_settings::{self, all_language_settings, AllLanguageSettings}, + File, +}; use settings::{update_settings_file, SettingsStore}; use std::{path::Path, sync::Arc}; use util::{paths, ResultExt}; @@ -27,7 +30,7 @@ pub struct CopilotButton { editor_subscription: Option<(Subscription, usize)>, editor_enabled: Option, language: Option>, - path: Option>, + file: Option>, fs: Arc, } @@ -41,7 +44,7 @@ impl View for CopilotButton { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let all_language_settings = &all_language_settings(cx); + let all_language_settings = all_language_settings(None, cx); if !all_language_settings.copilot.feature_enabled { return Empty::new().into_any(); } @@ -165,7 +168,7 @@ impl CopilotButton { editor_subscription: None, editor_enabled: None, language: None, - path: None, + file: None, fs, } } @@ -212,9 +215,9 @@ impl CopilotButton { let settings = settings::get::(cx); - if let Some(path) = self.path.as_ref() { - let path_enabled = settings.copilot_enabled_for_path(path); - let path = path.clone(); + if let Some(file) = &self.file { + let path = file.path().clone(); + let path_enabled = settings.copilot_enabled_for_path(&path); menu_options.push(ContextMenuItem::handler( format!( "{} Suggestions for This Path", @@ -279,14 +282,16 @@ impl CopilotButton { let language_name = snapshot .language_at(suggestion_anchor) .map(|language| language.name()); - let path = snapshot.file_at(suggestion_anchor).map(|file| file.path()); + let file = snapshot.file_at(suggestion_anchor).cloned(); self.editor_enabled = Some( - all_language_settings(cx) - .copilot_enabled(language_name.as_deref(), path.map(|p| p.as_ref())), + all_language_settings(self.file.as_ref().map(|f| f.as_ref()), cx).copilot_enabled( + language_name.as_deref(), + file.as_ref().map(|file| file.path().as_ref()), + ), ); self.language = language_name; - self.path = path.cloned(); + self.file = file; cx.notify() } @@ -363,14 +368,15 @@ async fn configure_disabled_globs( } fn toggle_copilot_globally(fs: Arc, cx: &mut AppContext) { - let show_copilot_suggestions = all_language_settings(cx).copilot_enabled(None, None); + let show_copilot_suggestions = all_language_settings(None, cx).copilot_enabled(None, None); update_settings_file::(fs, cx, move |file| { file.defaults.show_copilot_suggestions = Some((!show_copilot_suggestions).into()) }); } fn toggle_copilot_for_language(language: Arc, fs: Arc, cx: &mut AppContext) { - let show_copilot_suggestions = all_language_settings(cx).copilot_enabled(Some(&language), None); + let show_copilot_suggestions = + all_language_settings(None, cx).copilot_enabled(Some(&language), None); update_settings_file::(fs, cx, move |file| { file.languages .entry(language) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f5d109e15b..4a9237f563 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3207,12 +3207,12 @@ impl Editor { snapshot: &MultiBufferSnapshot, cx: &mut ViewContext, ) -> bool { - let path = snapshot.file_at(location).map(|file| file.path().as_ref()); + let file = snapshot.file_at(location); let language_name = snapshot .language_at(location) .map(|language| language.name()); - let settings = all_language_settings(cx); - settings.copilot_enabled(language_name.as_deref(), path) + let settings = all_language_settings(file.map(|f| f.as_ref() as _), cx); + settings.copilot_enabled(language_name.as_deref(), file.map(|f| f.path().as_ref())) } fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool { @@ -7076,11 +7076,13 @@ impl Editor { }; // If None, we are in a file without an extension - let file_extension = file_extension.or(self + let file = self .buffer .read(cx) .as_singleton() - .and_then(|b| b.read(cx).file()) + .and_then(|b| b.read(cx).file()); + let file_extension = file_extension.or(file + .as_ref() .and_then(|file| Path::new(file.file_name(cx)).extension()) .and_then(|e| e.to_str()) .map(|a| a.to_string())); @@ -7091,7 +7093,8 @@ impl Editor { .get("vim_mode") == Some(&serde_json::Value::Bool(true)); let telemetry_settings = *settings::get::(cx); - let copilot_enabled = all_language_settings(cx).copilot_enabled(None, None); + let copilot_enabled = + all_language_settings(file.map(|f| f.as_ref()), cx).copilot_enabled(None, None); let copilot_enabled_for_language = self .buffer .read(cx) diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 70aaca03c4..e4e283bd7e 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -26,8 +26,14 @@ pub fn language_settings<'a>( .language(language) } -pub fn all_language_settings<'a>(cx: &'a AppContext) -> &'a AllLanguageSettings { - settings::get::(cx) +pub fn all_language_settings<'a>( + file: Option<&dyn File>, + cx: &'a AppContext, +) -> &'a AllLanguageSettings { + settings::get_local::( + file.map(|f| (f.worktree_id(), f.path().as_ref())), + cx, + ) } #[derive(Debug, Clone)] diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 3cc4a181c5..c871bf0b96 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -28,7 +28,7 @@ use gpui::{ ModelHandle, Task, WeakModelHandle, }; use language::{ - language_settings::{all_language_settings, language_settings, FormatOnSave, Formatter}, + language_settings::{language_settings, FormatOnSave, Formatter}, point_to_lsp, proto::{ deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version, @@ -689,18 +689,15 @@ impl Project { } fn on_settings_changed(&mut self, cx: &mut ModelContext) { - let settings = all_language_settings(cx); - let mut language_servers_to_start = Vec::new(); 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 settings - .language(Some(&language.name())) - .enable_language_server - { + 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())); } } @@ -708,18 +705,22 @@ impl Project { } let mut language_servers_to_stop = Vec::new(); - for language in self.languages.to_vec() { - for lsp_adapter in language.lsp_adapters() { - if !settings - .language(Some(&language.name())) + let languages = self.languages.to_vec(); + for (worktree_id, started_lsp_name) in self.language_server_ids.keys() { + let language = languages.iter().find(|l| { + l.lsp_adapters() + .iter() + .any(|adapter| &adapter.name == started_lsp_name) + }); + 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) .enable_language_server { - let lsp_name = &lsp_adapter.name; - for (worktree_id, started_lsp_name) in self.language_server_ids.keys() { - if lsp_name == started_lsp_name { - language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); - } - } + language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); } } } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 7432eb8d40..5d121adc63 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -679,7 +679,7 @@ impl Worktree { } pub fn root_file(&self, cx: &mut ModelContext) -> Option { - let entry = self.entry_for_path("")?; + let entry = self.root_entry()?; Some(File { worktree: cx.handle(), path: entry.path.clone(),