Detailed changes
@@ -70,27 +70,30 @@ pub const CONNECTION_TIMEOUT: Duration = Duration::from_secs(5);
actions!(client, [SignIn, SignOut]);
-pub fn init(client: Arc<Client>, cx: &mut AppContext) {
+pub fn init(client: &Arc<Client>, cx: &mut AppContext) {
+ let client = Arc::downgrade(client);
settings::register_setting::<TelemetrySettings>(cx);
cx.add_global_action({
let client = client.clone();
move |_: &SignIn, cx| {
- let client = client.clone();
- cx.spawn(
- |cx| async move { client.authenticate_and_connect(true, &cx).log_err().await },
- )
- .detach();
+ if let Some(client) = client.upgrade() {
+ cx.spawn(
+ |cx| async move { client.authenticate_and_connect(true, &cx).log_err().await },
+ )
+ .detach();
+ }
}
});
cx.add_global_action({
let client = client.clone();
move |_: &SignOut, cx| {
- let client = client.clone();
- cx.spawn(|cx| async move {
- client.disconnect(&cx);
- })
- .detach();
+ if let Some(client) = client.upgrade() {
+ cx.spawn(|cx| async move {
+ client.disconnect(&cx);
+ })
+ .detach();
+ }
}
});
}
@@ -19,7 +19,7 @@ use gpui::{
use language::LanguageRegistry;
use parking_lot::Mutex;
use project::{Project, WorktreeId};
-use settings::Settings;
+use settings::{Settings, SettingsStore};
use std::{
cell::{Ref, RefCell, RefMut},
env,
@@ -102,6 +102,7 @@ impl TestServer {
async fn create_client(&mut self, cx: &mut TestAppContext, name: &str) -> TestClient {
cx.update(|cx| {
+ cx.set_global(SettingsStore::test(cx));
cx.set_global(Settings::test(cx));
});
@@ -185,6 +186,8 @@ impl TestServer {
})
});
+ cx.update(|cx| client::init(&client, cx));
+
let fs = FakeFs::new(cx.background());
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
let app_state = Arc::new(workspace::AppState {
@@ -20,7 +20,7 @@ use rand::{
prelude::*,
};
use serde::{Deserialize, Serialize};
-use settings::Settings;
+use settings::{Settings, SettingsStore};
use std::{
env,
ops::Range,
@@ -148,8 +148,11 @@ async fn test_random_collaboration(
for (client, mut cx) in clients {
cx.update(|cx| {
+ let store = cx.remove_global::<SettingsStore>();
+ let settings = cx.remove_global::<Settings>();
cx.clear_globals();
- cx.set_global(Settings::test(cx));
+ cx.set_global(store);
+ cx.set_global(settings);
drop(client);
});
}
@@ -34,13 +34,13 @@ impl<'a> EditorLspTestContext<'a> {
) -> EditorLspTestContext<'a> {
use json::json;
+ let app_state = cx.update(AppState::test);
+
cx.update(|cx| {
crate::init(cx);
pane::init(cx);
});
- let app_state = cx.update(AppState::test);
-
let file_name = format!(
"file.{}",
language
@@ -1174,7 +1174,7 @@ impl AppContext {
this.notify_global(type_id);
result
} else {
- panic!("No global added for {}", std::any::type_name::<T>());
+ panic!("no global added for {}", std::any::type_name::<T>());
}
}
@@ -1182,6 +1182,15 @@ impl AppContext {
self.globals.clear();
}
+ pub fn remove_global<T: 'static>(&mut self) -> T {
+ *self
+ .globals
+ .remove(&TypeId::of::<T>())
+ .unwrap_or_else(|| panic!("no global added for {}", std::any::type_name::<T>()))
+ .downcast()
+ .unwrap()
+ }
+
pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
where
T: Entity,
@@ -122,11 +122,11 @@ impl SettingsStore {
/// Add a new type of setting to the store.
pub fn register_setting<T: Setting>(&mut self, cx: &AppContext) {
let setting_type_id = TypeId::of::<T>();
-
let entry = self.setting_values.entry(setting_type_id);
if matches!(entry, hash_map::Entry::Occupied(_)) {
- panic!("duplicate setting type: {}", type_name::<T>());
+ return;
}
+
let setting_value = entry.or_insert(Box::new(SettingValue::<T> {
global_value: None,
local_values: Vec::new(),
@@ -142,6 +142,7 @@ impl SettingsStore {
user_values_stack = vec![user_value];
}
}
+
if let Some(default_deserialized_value) = default_settings.typed.get(&setting_type_id) {
setting_value.set_global_value(setting_value.load_setting(
default_deserialized_value,
@@ -159,7 +160,7 @@ impl SettingsStore {
pub fn get<T: Setting>(&self, path: Option<&Path>) -> &T {
self.setting_values
.get(&TypeId::of::<T>())
- .expect("unregistered setting type")
+ .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::<T>()))
.value_for_path(path)
.downcast_ref::<T>()
.expect("no default value for setting type")
@@ -175,6 +176,14 @@ impl SettingsStore {
.map_or(&serde_json::Value::Null, |s| &s.untyped)
}
+ #[cfg(any(test, feature = "test-support"))]
+ pub fn test(cx: &AppContext) -> Self {
+ let mut this = Self::default();
+ this.set_default_settings(&crate::test_settings(), cx)
+ .unwrap();
+ this
+ }
+
/// Override the global value for a particular setting.
///
/// This is only for tests. Normally, settings are only loaded from
@@ -183,7 +192,7 @@ impl SettingsStore {
pub fn replace_value<T: Setting>(&mut self, value: T) {
self.setting_values
.get_mut(&TypeId::of::<T>())
- .expect("unregistered setting type")
+ .unwrap_or_else(|| panic!("unregistered setting type {}", type_name::<T>()))
.set_global_value(Box::new(value))
}
@@ -268,7 +277,7 @@ impl SettingsStore {
pub fn set_default_settings(
&mut self,
default_settings_content: &str,
- cx: &mut AppContext,
+ cx: &AppContext,
) -> Result<()> {
let deserialized_setting_map = self.load_setting_map(default_settings_content)?;
if deserialized_setting_map.typed.len() != self.setting_values.len() {
@@ -290,7 +299,7 @@ impl SettingsStore {
pub fn set_user_settings(
&mut self,
user_settings_content: &str,
- cx: &mut AppContext,
+ cx: &AppContext,
) -> Result<()> {
let user_settings = self.load_setting_map(user_settings_content)?;
let old_user_settings =
@@ -304,7 +313,7 @@ impl SettingsStore {
&mut self,
path: Arc<Path>,
settings_content: Option<&str>,
- cx: &mut AppContext,
+ cx: &AppContext,
) -> Result<()> {
let removed_map = if let Some(settings_content) = settings_content {
self.local_deserialized_settings
@@ -18,11 +18,12 @@ impl<'a> VimTestContext<'a> {
pub async fn new(cx: &'a mut gpui::TestAppContext, enabled: bool) -> VimTestContext<'a> {
let mut cx = EditorLspTestContext::new_rust(Default::default(), cx).await;
cx.update(|cx| {
+ search::init(cx);
+ crate::init(cx);
+
cx.update_global(|store: &mut SettingsStore, _| {
store.replace_value(VimModeSetting(enabled));
});
- search::init(cx);
- crate::init(cx);
settings::KeymapFileContent::load("keymaps/vim.json", cx).unwrap();
});
@@ -369,8 +369,8 @@ pub struct AppState {
impl AppState {
#[cfg(any(test, feature = "test-support"))]
pub fn test(cx: &mut AppContext) -> Arc<Self> {
- let settings = Settings::test(cx);
- cx.set_global(settings);
+ cx.set_global(settings::SettingsStore::test(cx));
+ cx.set_global(Settings::test(cx));
let fs = fs::FakeFs::new(cx.background().clone());
let languages = Arc::new(LanguageRegistry::test());
@@ -378,6 +378,9 @@ impl AppState {
let client = Client::new(http_client.clone(), cx);
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx));
let themes = ThemeRegistry::new((), cx.font_cache().clone());
+
+ client::init(&client, cx);
+
Arc::new(Self {
client,
themes,
@@ -158,7 +158,7 @@ fn main() {
context_menu::init(cx);
project::Project::init(&client);
- client::init(client.clone(), cx);
+ client::init(&client, cx);
command_palette::init(cx);
editor::init(cx);
go_to_line::init(cx);
@@ -1283,9 +1283,7 @@ mod tests {
#[gpui::test]
async fn test_pane_actions(cx: &mut TestAppContext) {
- init(cx);
-
- let app_state = cx.update(AppState::test);
+ let app_state = init(cx);
app_state
.fs
.as_fake()