From 31aeb56e3af772aecaf129264eae170d9dbeef61 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Tue, 16 Sep 2025 11:00:28 -0600 Subject: [PATCH] Project --- crates/language/src/language_settings.rs | 6 +- crates/project/src/agent_server_store.rs | 2 +- crates/project/src/lsp_store.rs | 3 +- crates/project/src/project.rs | 86 +++---------------- crates/project/src/project_settings.rs | 2 +- crates/project/src/project_tests.rs | 16 ++-- .../settings/src/settings_content/language.rs | 9 ++ 7 files changed, 34 insertions(+), 90 deletions(-) diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index f2c43cb34303f50c5cd6c8e76c74ef25811bc262..72271dbd58c5def6a4017a94e811289f2f5d8b8a 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -13,9 +13,9 @@ use schemars::{JsonSchema, json_schema}; use serde::{Deserialize, Serialize}; pub use settings::{ - CompletionSettings, EditPredictionProvider, EditPredictionsMode, FormatOnSave, - IndentGuideSettings, LanguageSettingsContent, LspInsertMode, RewrapBehavior, - ShowWhitespaceSetting, SoftWrap, WordsCompletionMode, + CompletionSettings, EditPredictionProvider, EditPredictionsMode, FormatOnSave, Formatter, + FormatterList, IndentGuideSettings, InlayHintKind, LanguageSettingsContent, LspInsertMode, + RewrapBehavior, SelectedFormatter, ShowWhitespaceSetting, SoftWrap, WordsCompletionMode, }; use settings::{ ParameterizedJsonSchema, Settings, SettingsContent, SettingsLocation, SettingsStore, SettingsUi, diff --git a/crates/project/src/agent_server_store.rs b/crates/project/src/agent_server_store.rs index 9c50f9060665ac459ec79c53028932961eb5a7fb..79ff8badaf87734cfc4786fcbf54bfb2d6b39b5a 100644 --- a/crates/project/src/agent_server_store.rs +++ b/crates/project/src/agent_server_store.rs @@ -23,7 +23,7 @@ use rpc::{ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{SettingsContent, SettingsKey, SettingsStore, SettingsUi}; -use util::{MergeFrom, ResultExt as _, debug_panic}; +use util::{ResultExt as _, debug_panic}; use crate::ProjectEnvironment; diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 2040b10bb39ceff6d9d6d06a5dbfb0f68f41a459..09b0c7b5351dd0b9bd4b03ff89a46f61e30a72ad 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -5816,7 +5816,8 @@ impl LspStore { buffer.read(cx).file(), cx, ) - .completions; + .completions + .clone(); if !completion_settings.lsp { return Task::ready(Ok(Vec::new())); } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index fde9087e3480256fd0afe7f698fa2317e086b920..b3b0daa4460df1e3a5a813252a9a159e4daf5003 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -29,7 +29,6 @@ use context_server_store::ContextServerStore; pub use environment::{EnvironmentErrorMessage, ProjectEnvironmentEvent}; use git::repository::get_git_committer; use git_store::{Repository, RepositoryId}; -use schemars::JsonSchema; pub mod search_history; mod yarn; @@ -101,10 +100,7 @@ use rpc::{ }; use search::{SearchInputKind, SearchQuery, SearchResult}; use search_history::SearchHistory; -use settings::{ - InvalidSettingsError, Settings, SettingsKey, SettingsLocation, SettingsSources, SettingsStore, - SettingsUi, -}; +use settings::{InvalidSettingsError, Settings, SettingsLocation, SettingsStore}; use smol::channel::Receiver; use snippet::Snippet; use snippet_provider::SnippetProvider; @@ -988,6 +984,7 @@ impl settings::Settings for DisableAiSettings { } fn refine(&mut self, content: &settings::SettingsContent, _cx: &mut App) { + // If disable_ai is true *in any file*, it is disabled. self.disable_ai = self.disable_ai || content.project.disable_ai.unwrap_or(false); } @@ -5644,7 +5641,6 @@ fn provide_inline_values( mod disable_ai_settings_tests { use super::*; use gpui::TestAppContext; - use rpc::proto::cancel_language_server_work::Work; use settings::Settings; #[gpui::test] @@ -5652,7 +5648,9 @@ mod disable_ai_settings_tests { cx.update(|cx| { let mut store = SettingsStore::new(cx, &settings::test_settings()); store.register_setting::(cx); - let ai_disabled = |cx| DisableAiSettings::get_global(cx).disable_ai; + fn ai_disabled(cx: &App) -> bool { + DisableAiSettings::get_global(cx).disable_ai + } // Test 1: Default is false (AI enabled) assert!(!ai_disabled(cx), "Default should allow AI"); @@ -5665,77 +5663,13 @@ mod disable_ai_settings_tests { }) .to_string(); - // Test 2: Global true, local false -> still disabled (local cannot re-enable) - store.set_user_settings(&disable_false, cx); + store.set_user_settings(&disable_false, cx).unwrap(); + store.set_global_settings(&disable_true, cx).unwrap(); assert!(ai_disabled(cx), "Local false cannot override global true"); - // Test 3: Global false, local true -> disabled (local can make more restrictive) - store.set_user_settings(&disable_false, cx); - store.set_local_settings( - WorktreeId::from_usize(0), - Path::new("project.json").into(), - settings::LocalSettingsKind::Settings, - Some(&disable_true), - cx, - ); - assert!(ai_disabled(cx), "Local true can override global false"); - store.clear_local_settings(WorktreeId::from_usize(0), cx); - - // Test 4: Server can only make more restrictive (set to true) - store.set_user_settings(&disable_false, cx); - store.set_server_settings(&disable_true, cx); - assert!( - ai_disabled(cx), - "Server can set to true even if user is false" - ); - - // Test 5: Server false cannot override user true - store.set_server_settings(&disable_false, cx); - store.set_user_settings(&disable_true, cx); - assert!(ai_disabled(cx), "Server false cannot override user true"); - - // Test 6: Multiple local settings, any true disables AI - store.set_local_settings( - WorktreeId::from_usize(0), - Path::new("a").into(), - settings::LocalSettingsKind::Settings, - Some(&disable_false), - cx, - ); - store.set_local_settings( - WorktreeId::from_usize(1), - Path::new("b").into(), - settings::LocalSettingsKind::Settings, - Some(&disable_true), - cx, - ); - store.set_local_settings( - WorktreeId::from_usize(2), - Path::new("c").into(), - settings::LocalSettingsKind::Settings, - Some(&disable_false), - cx, - ); - store.set_user_settings(&disable_false, cx); - assert!(ai_disabled(cx), "Any local true should disable AI"); - store.clear_local_settings(WorktreeId::from_usize(0), cx); - store.clear_local_settings(WorktreeId::from_usize(1), cx); - store.clear_local_settings(WorktreeId::from_usize(2), cx); - - // Test 7: All three sources can independently disable AI - store.set_server_settings(&disable_false, cx); - store.set_user_settings(&disable_false, cx); - store.set_local_settings( - WorktreeId::from_usize(0), - Path::new("a").into(), - settings::LocalSettingsKind::Settings, - Some(&disable_true), - cx, - ); - assert!( - ai_disabled(cx), - "Local can disable even if user and server are false" - ); + store.set_global_settings(&disable_false, cx).unwrap(); + store.set_user_settings(&disable_true, cx).unwrap(); + assert!(ai_disabled(cx), "Local false cannot override global true"); }); } } diff --git a/crates/project/src/project_settings.rs b/crates/project/src/project_settings.rs index 0d3cda3b8fd5beb89ac8aa8ffc119c6e5a5400da..f6fc66dcc6fd60c49b77e0dcb8c0097c2a27588f 100644 --- a/crates/project/src/project_settings.rs +++ b/crates/project/src/project_settings.rs @@ -19,7 +19,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{ InvalidSettingsError, LocalSettingsKind, Settings, SettingsKey, SettingsLocation, - SettingsSources, SettingsStore, SettingsUi, parse_json_with_comments, watch_config_file, + SettingsStore, SettingsUi, parse_json_with_comments, watch_config_file, }; use std::{ collections::BTreeMap, diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 3745b1fdd0a784bc90fcd787c1f5454672b4b429..5daaa09b9bafc7aa6419e017f2c378a020bdba91 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -23,7 +23,7 @@ use language::{ Diagnostic, DiagnosticEntry, DiagnosticSet, DiagnosticSourceKind, DiskState, FakeLspAdapter, LanguageConfig, LanguageMatcher, LanguageName, LineEnding, ManifestName, ManifestProvider, ManifestQuery, OffsetRangeExt, Point, ToPoint, ToolchainList, ToolchainLister, - language_settings::{AllLanguageSettings, LanguageSettingsContent, language_settings}, + language_settings::{LanguageSettingsContent, language_settings}, tree_sitter_rust, tree_sitter_typescript, }; use lsp::{ @@ -2246,8 +2246,8 @@ async fn test_toggling_enable_language_server(cx: &mut gpui::TestAppContext) { // Disable Rust language server, ensuring only that server gets stopped. cx.update(|cx| { SettingsStore::update_global(cx, |settings, cx| { - settings.update_user_settings::(cx, |settings| { - settings.languages.0.insert( + settings.update_user_settings(cx, |settings| { + settings.languages_mut().insert( "Rust".into(), LanguageSettingsContent { enable_language_server: Some(false), @@ -2265,16 +2265,16 @@ async fn test_toggling_enable_language_server(cx: &mut gpui::TestAppContext) { // former gets started again and that the latter stops. cx.update(|cx| { SettingsStore::update_global(cx, |settings, cx| { - settings.update_user_settings::(cx, |settings| { - settings.languages.0.insert( - LanguageName::new("Rust"), + settings.update_user_settings(cx, |settings| { + settings.languages_mut().insert( + "Rust".into(), LanguageSettingsContent { enable_language_server: Some(true), ..Default::default() }, ); - settings.languages.0.insert( - LanguageName::new("JavaScript"), + settings.languages_mut().insert( + "JavaScript".into(), LanguageSettingsContent { enable_language_server: Some(false), ..Default::default() diff --git a/crates/settings/src/settings_content/language.rs b/crates/settings/src/settings_content/language.rs index ced6140c85dffca07028f3059fdeca9b94631d4c..c86c36954a022c20aac184c993be2b59117c9958 100644 --- a/crates/settings/src/settings_content/language.rs +++ b/crates/settings/src/settings_content/language.rs @@ -803,6 +803,15 @@ impl Default for FormatterList { } } +impl AsRef<[Formatter]> for FormatterList { + fn as_ref(&self) -> &[Formatter] { + match &self { + Self::Single(single) => std::slice::from_ref(single), + Self::Vec(v) => v, + } + } +} + /// Controls which formatter should be used when formatting code. If there are multiple formatters, they are executed in the order of declaration. #[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")]