From 43eb7f28d1f9817dbc7b34a8ccd9726a442f3460 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Wed, 8 Nov 2023 23:16:04 -0800 Subject: [PATCH] checkpoint --- crates/client2/src/test.rs | 2 +- crates/collab2/src/db/tests/db_tests.rs | 2 +- crates/collab2/src/tests/editor_tests.rs | 4 +- crates/collab2/src/tests/integration_tests.rs | 752 ----------------- crates/collab2/src/tests/test_server.rs | 4 +- crates/copilot2/src/copilot2.rs | 43 +- crates/editor2/src/editor_tests.rs | 757 ++++++++---------- crates/editor2/src/test.rs | 2 + .../editor2/src/test/editor_test_context.rs | 2 +- crates/gpui2/src/app.rs | 17 +- crates/gpui2/src/app/async_context.rs | 22 +- crates/gpui2/src/app/model_context.rs | 13 +- crates/gpui2/src/app/test_context.rs | 15 +- crates/gpui2/src/color.rs | 33 + crates/gpui2/src/gpui2.rs | 10 +- crates/gpui2/src/window.rs | 78 +- crates/language2/src/language2.rs | 4 +- crates/prettier2/src/prettier2.rs | 10 +- crates/project2/src/project2.rs | 2 +- crates/project2/src/project_tests.rs | 68 +- crates/rpc2/src/peer.rs | 20 +- crates/workspace2/src/workspace2.rs | 38 +- 22 files changed, 591 insertions(+), 1307 deletions(-) diff --git a/crates/client2/src/test.rs b/crates/client2/src/test.rs index 5462799103..086cbd570e 100644 --- a/crates/client2/src/test.rs +++ b/crates/client2/src/test.rs @@ -36,7 +36,7 @@ impl FakeServer { peer: Peer::new(0), state: Default::default(), user_id: client_user_id, - executor: cx.executor().clone(), + executor: cx.executor(), }; client diff --git a/crates/collab2/src/db/tests/db_tests.rs b/crates/collab2/src/db/tests/db_tests.rs index 98d1fee8fa..1f825efd74 100644 --- a/crates/collab2/src/db/tests/db_tests.rs +++ b/crates/collab2/src/db/tests/db_tests.rs @@ -510,7 +510,7 @@ fn test_fuzzy_like_string() { #[gpui::test] async fn test_fuzzy_search_users(cx: &mut TestAppContext) { - let test_db = TestDb::postgres(cx.executor().clone()); + let test_db = TestDb::postgres(cx.executor()); let db = test_db.db(); for (i, github_login) in [ "California", diff --git a/crates/collab2/src/tests/editor_tests.rs b/crates/collab2/src/tests/editor_tests.rs index 31082f75c0..5d1378a882 100644 --- a/crates/collab2/src/tests/editor_tests.rs +++ b/crates/collab2/src/tests/editor_tests.rs @@ -48,9 +48,9 @@ async fn test_host_disconnect( assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared())); - let window_b = + let workspace_b = cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx)); - let workspace_b = window_b.root(cx_b); + let editor_b = workspace_b .update(cx_b, |workspace, cx| { workspace.open_path((worktree_id, "b.txt"), None, true, cx) diff --git a/crates/collab2/src/tests/integration_tests.rs b/crates/collab2/src/tests/integration_tests.rs index 00c6c591b1..121a98c1d2 100644 --- a/crates/collab2/src/tests/integration_tests.rs +++ b/crates/collab2/src/tests/integration_tests.rs @@ -5717,755 +5717,3 @@ async fn test_join_call_after_screen_was_shared( ); }); } - -#[gpui::test(iterations = 10)] -async fn test_on_input_format_from_host_to_guest( - executor: BackgroundExecutor, - cx_a: &mut TestAppContext, - cx_b: &mut TestAppContext, -) { - let mut server = TestServer::start(&executor).await; - let client_a = server.create_client(cx_a, "user_a").await; - let client_b = server.create_client(cx_b, "user_b").await; - server - .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) - .await; - let active_call_a = cx_a.read(ActiveCall::global); - - // Set up a fake language server. - let mut language = Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ); - let mut fake_language_servers = language - .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { - capabilities: lsp::ServerCapabilities { - document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions { - first_trigger_character: ":".to_string(), - more_trigger_character: Some(vec![">".to_string()]), - }), - ..Default::default() - }, - ..Default::default() - })) - .await; - client_a.language_registry().add(Arc::new(language)); - - client_a - .fs() - .insert_tree( - "/a", - json!({ - "main.rs": "fn main() { a }", - "other.rs": "// Test file", - }), - ) - .await; - let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await; - let project_id = active_call_a - .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) - .await - .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; - - // Open a file in an editor as the host. - let buffer_a = project_a - .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx)) - .await - .unwrap(); - let window_a = cx_a.add_window(|_| EmptyView); - let editor_a = window_a.add_view(cx_a, |cx| { - Editor::for_buffer(buffer_a, Some(project_a.clone()), cx) - }); - - let fake_language_server = fake_language_servers.next().await.unwrap(); - executor.run_until_parked(); - - // Receive an OnTypeFormatting request as the host's language server. - // Return some formattings from the host's language server. - fake_language_server.handle_request::( - |params, _| async move { - assert_eq!( - params.text_document_position.text_document.uri, - lsp::Url::from_file_path("/a/main.rs").unwrap(), - ); - assert_eq!( - params.text_document_position.position, - lsp::Position::new(0, 14), - ); - - Ok(Some(vec![lsp::TextEdit { - new_text: "~<".to_string(), - range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)), - }])) - }, - ); - - // Open the buffer on the guest and see that the formattings worked - let buffer_b = project_b - .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx)) - .await - .unwrap(); - - // Type a on type formatting trigger character as the guest. - editor_a.update(cx_a, |editor, cx| { - cx.focus(&editor_a); - editor.change_selections(None, cx, |s| s.select_ranges([13..13])); - editor.handle_input(">", cx); - }); - - executor.run_until_parked(); - - buffer_b.read_with(cx_b, |buffer, _| { - assert_eq!(buffer.text(), "fn main() { a>~< }") - }); - - // Undo should remove LSP edits first - editor_a.update(cx_a, |editor, cx| { - assert_eq!(editor.text(cx), "fn main() { a>~< }"); - editor.undo(&Undo, cx); - assert_eq!(editor.text(cx), "fn main() { a> }"); - }); - executor.run_until_parked(); - - buffer_b.read_with(cx_b, |buffer, _| { - assert_eq!(buffer.text(), "fn main() { a> }") - }); - - editor_a.update(cx_a, |editor, cx| { - assert_eq!(editor.text(cx), "fn main() { a> }"); - editor.undo(&Undo, cx); - assert_eq!(editor.text(cx), "fn main() { a }"); - }); - executor.run_until_parked(); - - buffer_b.read_with(cx_b, |buffer, _| { - assert_eq!(buffer.text(), "fn main() { a }") - }); -} - -#[gpui::test(iterations = 10)] -async fn test_on_input_format_from_guest_to_host( - executor: BackgroundExecutor, - cx_a: &mut TestAppContext, - cx_b: &mut TestAppContext, -) { - let mut server = TestServer::start(&executor).await; - let client_a = server.create_client(cx_a, "user_a").await; - let client_b = server.create_client(cx_b, "user_b").await; - server - .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) - .await; - let active_call_a = cx_a.read(ActiveCall::global); - - // Set up a fake language server. - let mut language = Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ); - let mut fake_language_servers = language - .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { - capabilities: lsp::ServerCapabilities { - document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions { - first_trigger_character: ":".to_string(), - more_trigger_character: Some(vec![">".to_string()]), - }), - ..Default::default() - }, - ..Default::default() - })) - .await; - client_a.language_registry().add(Arc::new(language)); - - client_a - .fs() - .insert_tree( - "/a", - json!({ - "main.rs": "fn main() { a }", - "other.rs": "// Test file", - }), - ) - .await; - let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await; - let project_id = active_call_a - .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) - .await - .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; - - // Open a file in an editor as the guest. - let buffer_b = project_b - .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx)) - .await - .unwrap(); - let window_b = cx_b.add_window(|_| EmptyView); - let editor_b = window_b.add_view(cx_b, |cx| { - Editor::for_buffer(buffer_b, Some(project_b.clone()), cx) - }); - - let fake_language_server = fake_language_servers.next().await.unwrap(); - executor.run_until_parked(); - // Type a on type formatting trigger character as the guest. - editor_b.update(cx_b, |editor, cx| { - editor.change_selections(None, cx, |s| s.select_ranges([13..13])); - editor.handle_input(":", cx); - cx.focus(&editor_b); - }); - - // Receive an OnTypeFormatting request as the host's language server. - // Return some formattings from the host's language server. - cx_a.foreground().start_waiting(); - fake_language_server - .handle_request::(|params, _| async move { - assert_eq!( - params.text_document_position.text_document.uri, - lsp::Url::from_file_path("/a/main.rs").unwrap(), - ); - assert_eq!( - params.text_document_position.position, - lsp::Position::new(0, 14), - ); - - Ok(Some(vec![lsp::TextEdit { - new_text: "~:".to_string(), - range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)), - }])) - }) - .next() - .await - .unwrap(); - cx_a.foreground().finish_waiting(); - - // Open the buffer on the host and see that the formattings worked - let buffer_a = project_a - .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx)) - .await - .unwrap(); - executor.run_until_parked(); - - buffer_a.read_with(cx_a, |buffer, _| { - assert_eq!(buffer.text(), "fn main() { a:~: }") - }); - - // Undo should remove LSP edits first - editor_b.update(cx_b, |editor, cx| { - assert_eq!(editor.text(cx), "fn main() { a:~: }"); - editor.undo(&Undo, cx); - assert_eq!(editor.text(cx), "fn main() { a: }"); - }); - executor.run_until_parked(); - - buffer_a.read_with(cx_a, |buffer, _| { - assert_eq!(buffer.text(), "fn main() { a: }") - }); - - editor_b.update(cx_b, |editor, cx| { - assert_eq!(editor.text(cx), "fn main() { a: }"); - editor.undo(&Undo, cx); - assert_eq!(editor.text(cx), "fn main() { a }"); - }); - executor.run_until_parked(); - - buffer_a.read_with(cx_a, |buffer, _| { - assert_eq!(buffer.text(), "fn main() { a }") - }); -} - -#[gpui::test(iterations = 10)] -async fn test_mutual_editor_inlay_hint_cache_update( - executor: BackgroundExecutor, - cx_a: &mut TestAppContext, - cx_b: &mut TestAppContext, -) { - let mut server = TestServer::start(&executor).await; - let client_a = server.create_client(cx_a, "user_a").await; - let client_b = server.create_client(cx_b, "user_b").await; - server - .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) - .await; - let active_call_a = cx_a.read(ActiveCall::global); - let active_call_b = cx_b.read(ActiveCall::global); - - cx_a.update(editor::init); - cx_b.update(editor::init); - - cx_a.update(|cx| { - cx.update_global(|store: &mut SettingsStore, cx| { - store.update_user_settings::(cx, |settings| { - settings.defaults.inlay_hints = Some(InlayHintSettings { - enabled: true, - show_type_hints: true, - show_parameter_hints: false, - show_other_hints: true, - }) - }); - }); - }); - cx_b.update(|cx| { - cx.update_global(|store: &mut SettingsStore, cx| { - store.update_user_settings::(cx, |settings| { - settings.defaults.inlay_hints = Some(InlayHintSettings { - enabled: true, - show_type_hints: true, - show_parameter_hints: false, - show_other_hints: true, - }) - }); - }); - }); - - let mut language = Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ); - let mut fake_language_servers = language - .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { - capabilities: lsp::ServerCapabilities { - inlay_hint_provider: Some(lsp::OneOf::Left(true)), - ..Default::default() - }, - ..Default::default() - })) - .await; - let language = Arc::new(language); - client_a.language_registry().add(Arc::clone(&language)); - client_b.language_registry().add(language); - - // Client A opens a project. - client_a - .fs() - .insert_tree( - "/a", - json!({ - "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out", - "other.rs": "// Test file", - }), - ) - .await; - let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await; - active_call_a - .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx)) - .await - .unwrap(); - let project_id = active_call_a - .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) - .await - .unwrap(); - - // Client B joins the project - let project_b = client_b.build_remote_project(project_id, cx_b).await; - active_call_b - .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) - .await - .unwrap(); - - let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a); - cx_a.foreground().start_waiting(); - - // The host opens a rust file. - let _buffer_a = project_a - .update(cx_a, |project, cx| { - project.open_local_buffer("/a/main.rs", cx) - }) - .await - .unwrap(); - let fake_language_server = fake_language_servers.next().await.unwrap(); - let editor_a = workspace_a - .update(cx_a, |workspace, cx| { - workspace.open_path((worktree_id, "main.rs"), None, true, cx) - }) - .await - .unwrap() - .downcast::() - .unwrap(); - - // Set up the language server to return an additional inlay hint on each request. - let edits_made = Arc::new(AtomicUsize::new(0)); - let closure_edits_made = Arc::clone(&edits_made); - fake_language_server - .handle_request::(move |params, _| { - let task_edits_made = Arc::clone(&closure_edits_made); - async move { - assert_eq!( - params.text_document.uri, - lsp::Url::from_file_path("/a/main.rs").unwrap(), - ); - let edits_made = task_edits_made.load(atomic::Ordering::Acquire); - Ok(Some(vec![lsp::InlayHint { - position: lsp::Position::new(0, edits_made as u32), - label: lsp::InlayHintLabel::String(edits_made.to_string()), - kind: None, - text_edits: None, - tooltip: None, - padding_left: None, - padding_right: None, - data: None, - }])) - } - }) - .next() - .await - .unwrap(); - - executor.run_until_parked(); - - let initial_edit = edits_made.load(atomic::Ordering::Acquire); - editor_a.update(cx_a, |editor, _| { - assert_eq!( - vec![initial_edit.to_string()], - extract_hint_labels(editor), - "Host should get its first hints when opens an editor" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 1, - "Host editor update the cache version after every cache/view change", - ); - }); - let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b); - let editor_b = workspace_b - .update(cx_b, |workspace, cx| { - workspace.open_path((worktree_id, "main.rs"), None, true, cx) - }) - .await - .unwrap() - .downcast::() - .unwrap(); - - executor.run_until_parked(); - editor_b.update(cx_b, |editor, _| { - assert_eq!( - vec![initial_edit.to_string()], - extract_hint_labels(editor), - "Client should get its first hints when opens an editor" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 1, - "Guest editor update the cache version after every cache/view change" - ); - }); - - let after_client_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1; - editor_b.update(cx_b, |editor, cx| { - editor.change_selections(None, cx, |s| s.select_ranges([13..13].clone())); - editor.handle_input(":", cx); - cx.focus(&editor_b); - }); - - executor.run_until_parked(); - editor_a.update(cx_a, |editor, _| { - assert_eq!( - vec![after_client_edit.to_string()], - extract_hint_labels(editor), - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.version(), 2); - }); - editor_b.update(cx_b, |editor, _| { - assert_eq!( - vec![after_client_edit.to_string()], - extract_hint_labels(editor), - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.version(), 2); - }); - - let after_host_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1; - editor_a.update(cx_a, |editor, cx| { - editor.change_selections(None, cx, |s| s.select_ranges([13..13])); - editor.handle_input("a change to increment both buffers' versions", cx); - cx.focus(&editor_a); - }); - - executor.run_until_parked(); - editor_a.update(cx_a, |editor, _| { - assert_eq!( - vec![after_host_edit.to_string()], - extract_hint_labels(editor), - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.version(), 3); - }); - editor_b.update(cx_b, |editor, _| { - assert_eq!( - vec![after_host_edit.to_string()], - extract_hint_labels(editor), - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!(inlay_cache.version(), 3); - }); - - let after_special_edit_for_refresh = edits_made.fetch_add(1, atomic::Ordering::Release) + 1; - fake_language_server - .request::(()) - .await - .expect("inlay refresh request failed"); - - executor.run_until_parked(); - editor_a.update(cx_a, |editor, _| { - assert_eq!( - vec![after_special_edit_for_refresh.to_string()], - extract_hint_labels(editor), - "Host should react to /refresh LSP request" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 4, - "Host should accepted all edits and bump its cache version every time" - ); - }); - editor_b.update(cx_b, |editor, _| { - assert_eq!( - vec![after_special_edit_for_refresh.to_string()], - extract_hint_labels(editor), - "Guest should get a /refresh LSP request propagated by host" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 4, - "Guest should accepted all edits and bump its cache version every time" - ); - }); -} - -#[gpui::test(iterations = 10)] -async fn test_inlay_hint_refresh_is_forwarded( - executor: BackgroundExecutor, - cx_a: &mut TestAppContext, - cx_b: &mut TestAppContext, -) { - let mut server = TestServer::start(&executor).await; - let client_a = server.create_client(cx_a, "user_a").await; - let client_b = server.create_client(cx_b, "user_b").await; - server - .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) - .await; - let active_call_a = cx_a.read(ActiveCall::global); - let active_call_b = cx_b.read(ActiveCall::global); - - cx_a.update(editor::init); - cx_b.update(editor::init); - - cx_a.update(|cx| { - cx.update_global(|store: &mut SettingsStore, cx| { - store.update_user_settings::(cx, |settings| { - settings.defaults.inlay_hints = Some(InlayHintSettings { - enabled: false, - show_type_hints: false, - show_parameter_hints: false, - show_other_hints: false, - }) - }); - }); - }); - cx_b.update(|cx| { - cx.update_global(|store: &mut SettingsStore, cx| { - store.update_user_settings::(cx, |settings| { - settings.defaults.inlay_hints = Some(InlayHintSettings { - enabled: true, - show_type_hints: true, - show_parameter_hints: true, - show_other_hints: true, - }) - }); - }); - }); - - let mut language = Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ); - let mut fake_language_servers = language - .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { - capabilities: lsp::ServerCapabilities { - inlay_hint_provider: Some(lsp::OneOf::Left(true)), - ..Default::default() - }, - ..Default::default() - })) - .await; - let language = Arc::new(language); - client_a.language_registry().add(Arc::clone(&language)); - client_b.language_registry().add(language); - - client_a - .fs() - .insert_tree( - "/a", - json!({ - "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out", - "other.rs": "// Test file", - }), - ) - .await; - let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await; - active_call_a - .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx)) - .await - .unwrap(); - let project_id = active_call_a - .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) - .await - .unwrap(); - - let project_b = client_b.build_remote_project(project_id, cx_b).await; - active_call_b - .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) - .await - .unwrap(); - - let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a); - let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b); - cx_a.foreground().start_waiting(); - cx_b.foreground().start_waiting(); - - let editor_a = workspace_a - .update(cx_a, |workspace, cx| { - workspace.open_path((worktree_id, "main.rs"), None, true, cx) - }) - .await - .unwrap() - .downcast::() - .unwrap(); - - let editor_b = workspace_b - .update(cx_b, |workspace, cx| { - workspace.open_path((worktree_id, "main.rs"), None, true, cx) - }) - .await - .unwrap() - .downcast::() - .unwrap(); - - let other_hints = Arc::new(AtomicBool::new(false)); - let fake_language_server = fake_language_servers.next().await.unwrap(); - let closure_other_hints = Arc::clone(&other_hints); - fake_language_server - .handle_request::(move |params, _| { - let task_other_hints = Arc::clone(&closure_other_hints); - async move { - assert_eq!( - params.text_document.uri, - lsp::Url::from_file_path("/a/main.rs").unwrap(), - ); - let other_hints = task_other_hints.load(atomic::Ordering::Acquire); - let character = if other_hints { 0 } else { 2 }; - let label = if other_hints { - "other hint" - } else { - "initial hint" - }; - Ok(Some(vec![lsp::InlayHint { - position: lsp::Position::new(0, character), - label: lsp::InlayHintLabel::String(label.to_string()), - kind: None, - text_edits: None, - tooltip: None, - padding_left: None, - padding_right: None, - data: None, - }])) - } - }) - .next() - .await - .unwrap(); - cx_a.foreground().finish_waiting(); - cx_b.foreground().finish_waiting(); - - executor.run_until_parked(); - editor_a.update(cx_a, |editor, _| { - assert!( - extract_hint_labels(editor).is_empty(), - "Host should get no hints due to them turned off" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 0, - "Turned off hints should not generate version updates" - ); - }); - - executor.run_until_parked(); - editor_b.update(cx_b, |editor, _| { - assert_eq!( - vec!["initial hint".to_string()], - extract_hint_labels(editor), - "Client should get its first hints when opens an editor" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 1, - "Should update cache verison after first hints" - ); - }); - - other_hints.fetch_or(true, atomic::Ordering::Release); - fake_language_server - .request::(()) - .await - .expect("inlay refresh request failed"); - executor.run_until_parked(); - editor_a.update(cx_a, |editor, _| { - assert!( - extract_hint_labels(editor).is_empty(), - "Host should get nop hints due to them turned off, even after the /refresh" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 0, - "Turned off hints should not generate version updates, again" - ); - }); - - executor.run_until_parked(); - editor_b.update(cx_b, |editor, _| { - assert_eq!( - vec!["other hint".to_string()], - extract_hint_labels(editor), - "Guest should get a /refresh LSP request propagated by host despite host hints are off" - ); - let inlay_cache = editor.inlay_hint_cache(); - assert_eq!( - inlay_cache.version(), - 2, - "Guest should accepted all edits and bump its cache version every time" - ); - }); -} - -fn extract_hint_labels(editor: &Editor) -> Vec { - let mut labels = Vec::new(); - for hint in editor.inlay_hint_cache().hints() { - match hint.label { - project::InlayHintLabel::String(s) => labels.push(s), - _ => unreachable!(), - } - } - labels -} diff --git a/crates/collab2/src/tests/test_server.rs b/crates/collab2/src/tests/test_server.rs index d0ab917d68..1b4d8945ae 100644 --- a/crates/collab2/src/tests/test_server.rs +++ b/crates/collab2/src/tests/test_server.rs @@ -208,11 +208,11 @@ impl TestServer { }) }); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); let user_store = cx.build_model(|cx| UserStore::new(client.clone(), http, cx)); let workspace_store = cx.build_model(|cx| WorkspaceStore::new(client.clone(), cx)); let mut language_registry = LanguageRegistry::test(); - language_registry.set_executor(cx.executor().clone()); + language_registry.set_executor(cx.executor()); let app_state = Arc::new(workspace::AppState { client: client.clone(), user_store: user_store.clone(), diff --git a/crates/copilot2/src/copilot2.rs b/crates/copilot2/src/copilot2.rs index 2daf2fec12..53d802dd03 100644 --- a/crates/copilot2/src/copilot2.rs +++ b/crates/copilot2/src/copilot2.rs @@ -351,28 +351,29 @@ impl Copilot { } } - // #[cfg(any(test, feature = "test-support"))] - // pub fn fake(cx: &mut gpui::TestAppContext) -> (ModelHandle, lsp::FakeLanguageServer) { - // use node_runtime::FakeNodeRuntime; + #[cfg(any(test, feature = "test-support"))] + pub fn fake(cx: &mut gpui::TestAppContext) -> (Model, lsp::FakeLanguageServer) { + use node_runtime::FakeNodeRuntime; - // let (server, fake_server) = - // LanguageServer::fake("copilot".into(), Default::default(), cx.to_async()); - // let http = util::http::FakeHttpClient::create(|_| async { unreachable!() }); - // let node_runtime = FakeNodeRuntime::new(); - // let this = cx.add_model(|_| Self { - // server_id: LanguageServerId(0), - // http: http.clone(), - // node_runtime, - // server: CopilotServer::Running(RunningCopilotServer { - // name: LanguageServerName(Arc::from("copilot")), - // lsp: Arc::new(server), - // sign_in_status: SignInStatus::Authorized, - // registered_buffers: Default::default(), - // }), - // buffers: Default::default(), - // }); - // (this, fake_server) - // } + let (server, fake_server) = + LanguageServer::fake("copilot".into(), Default::default(), cx.to_async()); + let http = util::http::FakeHttpClient::create(|_| async { unreachable!() }); + let node_runtime = FakeNodeRuntime::new(); + let this = cx.build_model(|cx| Self { + server_id: LanguageServerId(0), + http: http.clone(), + node_runtime, + server: CopilotServer::Running(RunningCopilotServer { + name: LanguageServerName(Arc::from("copilot")), + lsp: Arc::new(server), + sign_in_status: SignInStatus::Authorized, + registered_buffers: Default::default(), + }), + _subscription: cx.on_app_quit(Self::shutdown_language_server), + buffers: Default::default(), + }); + (this, fake_server) + } fn start_language_server( new_server_id: LanguageServerId, diff --git a/crates/editor2/src/editor_tests.rs b/crates/editor2/src/editor_tests.rs index 898f53687b..08c44d7682 100644 --- a/crates/editor2/src/editor_tests.rs +++ b/crates/editor2/src/editor_tests.rs @@ -11,7 +11,7 @@ use drag_and_drop::DragAndDrop; use futures::StreamExt; use gpui::{ serde_json::{self, json}, - TestAppContext, + TestAppContext, WindowOptions, }; use indoc::indoc; use language::{ @@ -31,7 +31,7 @@ use util::{ test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker}, }; use workspace::{ - item::{FollowableItem, Item, ItemHandle}, + item::{FollowableEvents, FollowableItem, Item, ItemHandle}, NavigationEntry, ViewId, }; @@ -46,36 +46,32 @@ fn test_edit_events(cx: &mut TestAppContext) { }); let events = Rc::new(RefCell::new(Vec::new())); - let editor1 = cx - .add_window({ - let events = events.clone(); - |cx| { - cx.subscribe(cx.view(), move |_, _, event, _| { - if matches!(event, Event::Edited | Event::BufferEdited) { - events.borrow_mut().push(("editor1", event.clone())); - } - }) - .detach(); - Editor::for_buffer(buffer.clone(), None, cx) - } - }) - .root(cx) - .unwrap(); - let editor2 = cx - .add_window({ - let events = events.clone(); - |cx| { - cx.subscribe(cx.view(), move |_, _, event, _| { - if matches!(event, Event::Edited | Event::BufferEdited) { - events.borrow_mut().push(("editor2", event.clone())); - } - }) - .detach(); - Editor::for_buffer(buffer.clone(), None, cx) - } - }) - .root(cx) - .unwrap(); + let editor1 = cx.add_window({ + let events = events.clone(); + |cx| { + cx.subscribe(cx.view(), move |_, _, event, _| { + if matches!(event, Event::Edited | Event::BufferEdited) { + events.borrow_mut().push(("editor1", event.clone())); + } + }) + .detach(); + Editor::for_buffer(buffer.clone(), None, cx) + } + }); + + let editor2 = cx.add_window({ + let events = events.clone(); + |cx| { + cx.subscribe(cx.view(), move |_, _, event, _| { + if matches!(event, Event::Edited | Event::BufferEdited) { + events.borrow_mut().push(("editor2", event.clone())); + } + }) + .detach(); + Editor::for_buffer(buffer.clone(), None, cx) + } + }); + assert_eq!(mem::take(&mut *events.borrow_mut()), []); // Mutating editor 1 will emit an `Edited` event only for that editor. @@ -108,8 +104,6 @@ fn test_edit_events(cx: &mut TestAppContext) { ("editor1", Event::Edited), ("editor1", Event::BufferEdited), ("editor2", Event::BufferEdited), - ("editor1", Event::DirtyChanged), - ("editor2", Event::DirtyChanged), ] ); @@ -121,8 +115,6 @@ fn test_edit_events(cx: &mut TestAppContext) { ("editor1", Event::Edited), ("editor1", Event::BufferEdited), ("editor2", Event::BufferEdited), - ("editor1", Event::DirtyChanged), - ("editor2", Event::DirtyChanged), ] ); @@ -134,8 +126,6 @@ fn test_edit_events(cx: &mut TestAppContext) { ("editor2", Event::Edited), ("editor1", Event::BufferEdited), ("editor2", Event::BufferEdited), - ("editor1", Event::DirtyChanged), - ("editor2", Event::DirtyChanged), ] ); @@ -147,8 +137,6 @@ fn test_edit_events(cx: &mut TestAppContext) { ("editor2", Event::Edited), ("editor1", Event::BufferEdited), ("editor2", Event::BufferEdited), - ("editor1", Event::DirtyChanged), - ("editor2", Event::DirtyChanged), ] ); @@ -166,12 +154,10 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) { init_test(cx, |_| {}); let mut now = Instant::now(); - let buffer = cx.add_model(|cx| language::Buffer::new(0, cx.model_id() as u64, "123456")); + let buffer = cx.build_model(|cx| language::Buffer::new(0, cx.entity_id().as_u64(), "123456")); let group_interval = buffer.read_with(cx, |buffer, _| buffer.transaction_group_interval()); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let editor = cx - .add_window(|cx| build_editor(buffer.clone(), cx)) - .root(cx); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let editor = cx.add_window(|cx| build_editor(buffer.clone(), cx)); editor.update(cx, |editor, cx| { editor.start_transaction_at(now, cx); @@ -238,14 +224,14 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) { fn test_ime_composition(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let buffer = cx.add_model(|cx| { - let mut buffer = language::Buffer::new(0, cx.model_id() as u64, "abcde"); + let buffer = cx.build_model(|cx| { + let mut buffer = language::Buffer::new(0, cx.entity_id().as_u64(), "abcde"); // Ensure automatic grouping doesn't occur. buffer.set_group_interval(Duration::ZERO); buffer }); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); cx.add_window(|cx| { let mut editor = build_editor(buffer.clone(), cx); @@ -341,55 +327,64 @@ fn test_ime_composition(cx: &mut TestAppContext) { fn test_selection_with_mouse(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let editor = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let editor = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx); + build_editor(buffer, cx) + }); + editor.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx); }); assert_eq!( - editor.update(cx, |view, cx| view.selections.display_ranges(cx)), + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)] ); editor.update(cx, |view, cx| { - view.update_selection(DisplayPoint::new(3, 3), 0, Point::::zero(), cx); + view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::::zero(), cx); }); assert_eq!( - editor.update(cx, |view, cx| view.selections.display_ranges(cx)), + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)] ); editor.update(cx, |view, cx| { - view.update_selection(DisplayPoint::new(1, 1), 0, Point::::zero(), cx); + view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::::zero(), cx); }); assert_eq!( - editor.update(cx, |view, cx| view.selections.display_ranges(cx)), + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)] ); editor.update(cx, |view, cx| { view.end_selection(cx); - view.update_selection(DisplayPoint::new(3, 3), 0, Point::::zero(), cx); + view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::::zero(), cx); }); assert_eq!( - editor.update(cx, |view, cx| view.selections.display_ranges(cx)), + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)] ); editor.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx); - view.update_selection(DisplayPoint::new(0, 0), 0, Point::::zero(), cx); + view.update_selection(DisplayPoint::new(0, 0), 0, gpui::Point::::zero(), cx); }); assert_eq!( - editor.update(cx, |view, cx| view.selections.display_ranges(cx)), + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), [ DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1), DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0) @@ -401,7 +396,9 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { }); assert_eq!( - editor.update(cx, |view, cx| view.selections.display_ranges(cx)), + editor + .update(cx, |view, cx| view.selections.display_ranges(cx)) + .unwrap(), [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)] ); } @@ -410,12 +407,10 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { fn test_canceling_pending_selection(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx); @@ -426,7 +421,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { }); view.update(cx, |view, cx| { - view.update_selection(DisplayPoint::new(3, 3), 0, Point::::zero(), cx); + view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::::zero(), cx); assert_eq!( view.selections.display_ranges(cx), [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)] @@ -435,7 +430,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { view.update(cx, |view, cx| { view.cancel(&Cancel, cx); - view.update_selection(DisplayPoint::new(1, 1), 0, Point::::zero(), cx); + view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::::zero(), cx); assert_eq!( view.selections.display_ranges(cx), [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)] @@ -458,12 +453,10 @@ fn test_clone(cx: &mut TestAppContext) { true, ); - let editor = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple(&text, cx); - build_editor(buffer, cx) - }) - .root(cx); + let editor = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple(&text, cx); + build_editor(buffer, cx) + }); editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone())); @@ -477,11 +470,9 @@ fn test_clone(cx: &mut TestAppContext) { ); }); - let cloned_editor = editor - .update(cx, |editor, cx| { - cx.add_window(Default::default(), |cx| editor.clone(cx)) - }) - .root(cx); + let cloned_editor = editor.update(cx, |editor, cx| { + cx.add_window(Default::default(), |cx| editor.clone(cx)) + }); let snapshot = editor.update(cx, |e, cx| e.snapshot(cx)); let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx)); @@ -513,11 +504,12 @@ async fn test_navigation_history(cx: &mut TestAppContext) { cx.set_global(DragAndDrop::::default()); use workspace::item::Item; - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); let project = Project::test(fs, [], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); - let workspace = window.root(cx); + let workspace = window; let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); + window.add_view(cx, |cx| { let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx); let mut editor = build_editor(buffer.clone(), cx); @@ -614,7 +606,7 @@ async fn test_navigation_history(cx: &mut TestAppContext) { ); assert_eq!( editor.scroll_position(cx), - vec2f(0., editor.max_point(cx).row() as f32) + Point::new(0., editor.max_point(cx).row() as f32) ); editor @@ -625,20 +617,28 @@ async fn test_navigation_history(cx: &mut TestAppContext) { fn test_cancel(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx); - view.update_selection(DisplayPoint::new(1, 1), 0, Point::::zero(), cx); + view.update_selection( + DisplayPoint::new(1, 1), + 0, + gpui::Point::::zero(), + cx, + ); view.end_selection(cx); view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx); - view.update_selection(DisplayPoint::new(0, 3), 0, Point::::zero(), cx); + view.update_selection( + DisplayPoint::new(0, 3), + 0, + gpui::Point::::zero(), + cx, + ); view.end_selection(cx); assert_eq!( view.selections.display_ranges(cx), @@ -670,10 +670,9 @@ fn test_cancel(cx: &mut TestAppContext) { fn test_fold_action(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple( - &" + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple( + &" impl Foo { // Hello! @@ -690,12 +689,11 @@ fn test_fold_action(cx: &mut TestAppContext) { } } " - .unindent(), - cx, - ); - build_editor(buffer.clone(), cx) - }) - .root(cx); + .unindent(), + cx, + ); + build_editor(buffer.clone(), cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { @@ -763,9 +761,7 @@ fn test_move_cursor(cx: &mut TestAppContext) { init_test(cx, |_| {}); let buffer = cx.update(|cx| MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx)); - let view = cx - .add_window(|cx| build_editor(buffer.clone(), cx)) - .root(cx); + let view = cx.add_window(|cx| build_editor(buffer.clone(), cx)); buffer.update(cx, |buffer, cx| { buffer.edit( @@ -840,12 +836,10 @@ fn test_move_cursor(cx: &mut TestAppContext) { fn test_move_cursor_multibyte(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε", cx); - build_editor(buffer.clone(), cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε", cx); + build_editor(buffer.clone(), cx) + }); assert_eq!('ⓐ'.len_utf8(), 3); assert_eq!('α'.len_utf8(), 2); @@ -958,12 +952,10 @@ fn test_move_cursor_multibyte(cx: &mut TestAppContext) { fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx); - build_editor(buffer.clone(), cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx); + build_editor(buffer.clone(), cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]); @@ -1010,12 +1002,10 @@ fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) { fn test_beginning_end_of_line(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\n def", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("abc\n def", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ @@ -1175,12 +1165,10 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { fn test_prev_next_word_boundary(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n {baz.qux()}", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n {baz.qux()}", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ @@ -1229,13 +1217,10 @@ fn test_prev_next_word_boundary(cx: &mut TestAppContext) { fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = - MultiBuffer::build_simple("use one::{\n two::three::four::five\n};", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("use one::{\n two::three::four::five\n};", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.set_wrap_width(Some(140.), cx); @@ -1293,7 +1278,7 @@ async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppCon let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); let window = cx.window; - window.simulate_resize(vec2f(100., 4. * line_height), &mut cx); + window.simulate_resize(Point::new(100., 4. * line_height), &mut cx); cx.set_state( &r#"ˇone @@ -1392,7 +1377,7 @@ async fn test_scroll_page_up_page_down(cx: &mut gpui::TestAppContext) { let mut cx = EditorTestContext::new(cx).await; let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); let window = cx.window; - window.simulate_resize(vec2f(1000., 4. * line_height + 0.5), &mut cx); + window.simulate_resize(Point::new(1000., 4. * line_height + 0.5), &mut cx); cx.set_state( &r#"ˇone @@ -1409,18 +1394,18 @@ async fn test_scroll_page_up_page_down(cx: &mut gpui::TestAppContext) { ); cx.update_editor(|editor, cx| { - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 0.)); editor.scroll_screen(&ScrollAmount::Page(1.), cx); - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 3.)); editor.scroll_screen(&ScrollAmount::Page(1.), cx); - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 6.)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 6.)); editor.scroll_screen(&ScrollAmount::Page(-1.), cx); - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 3.)); editor.scroll_screen(&ScrollAmount::Page(-0.5), cx); - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 1.)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 1.)); editor.scroll_screen(&ScrollAmount::Page(0.5), cx); - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 3.)); }); } @@ -1435,7 +1420,7 @@ async fn test_autoscroll(cx: &mut gpui::TestAppContext) { }); let window = cx.window; - window.simulate_resize(vec2f(1000., 6.0 * line_height), &mut cx); + window.simulate_resize(Point::new(1000., 6.0 * line_height), &mut cx); cx.set_state( &r#"ˇone @@ -1451,7 +1436,7 @@ async fn test_autoscroll(cx: &mut gpui::TestAppContext) { "#, ); cx.update_editor(|editor, cx| { - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.0)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 0.0)); }); // Add a cursor below the visible area. Since both cursors cannot fit @@ -1466,7 +1451,7 @@ async fn test_autoscroll(cx: &mut gpui::TestAppContext) { }) }); cx.update_editor(|editor, cx| { - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.0)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 3.0)); }); // Move down. The editor cursor scrolls down to track the newest cursor. @@ -1474,7 +1459,7 @@ async fn test_autoscroll(cx: &mut gpui::TestAppContext) { editor.move_down(&Default::default(), cx); }); cx.update_editor(|editor, cx| { - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 4.0)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 4.0)); }); // Add a cursor above the visible area. Since both cursors fit on screen, @@ -1488,7 +1473,7 @@ async fn test_autoscroll(cx: &mut gpui::TestAppContext) { }) }); cx.update_editor(|editor, cx| { - assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 1.0)); + assert_eq!(editor.snapshot(cx).scroll_position(), Point::new(0., 1.0)); }); } @@ -1499,7 +1484,7 @@ async fn test_move_page_up_page_down(cx: &mut gpui::TestAppContext) { let line_height = cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache())); let window = cx.window; - window.simulate_resize(vec2f(100., 4. * line_height), &mut cx); + window.simulate_resize(Point::new(100., 4. * line_height), &mut cx); cx.set_state( &r#" @@ -1623,12 +1608,10 @@ async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) { fn test_delete_to_word_boundary(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("one two three four", cx); - build_editor(buffer.clone(), cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("one two three four", cx); + build_editor(buffer.clone(), cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { @@ -1661,12 +1644,10 @@ fn test_delete_to_word_boundary(cx: &mut TestAppContext) { fn test_newline(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("aaaa\n bbbb\n", cx); - build_editor(buffer.clone(), cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("aaaa\n bbbb\n", cx); + build_editor(buffer.clone(), cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { @@ -1686,10 +1667,9 @@ fn test_newline(cx: &mut TestAppContext) { fn test_newline_with_old_selections(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let editor = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple( - " + let editor = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple( + " a b( X @@ -1698,20 +1678,19 @@ fn test_newline_with_old_selections(cx: &mut TestAppContext) { X ) " - .unindent() - .as_str(), - cx, - ); - let mut editor = build_editor(buffer.clone(), cx); - editor.change_selections(None, cx, |s| { - s.select_ranges([ - Point::new(2, 4)..Point::new(2, 5), - Point::new(5, 4)..Point::new(5, 5), - ]) - }); - editor - }) - .root(cx); + .unindent() + .as_str(), + cx, + ); + let mut editor = build_editor(buffer.clone(), cx); + editor.change_selections(None, cx, |s| { + s.select_ranges([ + Point::new(2, 4)..Point::new(2, 5), + Point::new(5, 4)..Point::new(5, 5), + ]) + }); + editor + }); editor.update(cx, |editor, cx| { // Edit the buffer directly, deleting ranges surrounding the editor's selections @@ -1916,14 +1895,12 @@ async fn test_newline_comments(cx: &mut gpui::TestAppContext) { fn test_insert_with_old_selections(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let editor = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx); - let mut editor = build_editor(buffer.clone(), cx); - editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20])); - editor - }) - .root(cx); + let editor = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx); + let mut editor = build_editor(buffer.clone(), cx); + editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20])); + editor + }); editor.update(cx, |editor, cx| { // Edit the buffer directly, deleting ranges surrounding the editor's selections @@ -2271,14 +2248,14 @@ fn test_indent_outdent_with_excerpts(cx: &mut TestAppContext) { None, )); - let toml_buffer = cx.add_model(|cx| { - Buffer::new(0, cx.model_id() as u64, "a = 1\nb = 2\n").with_language(toml_language, cx) + let toml_buffer = cx.build_model(|cx| { + Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n").with_language(toml_language, cx) }); - let rust_buffer = cx.add_model(|cx| { - Buffer::new(0, cx.model_id() as u64, "const c: usize = 3;\n") + let rust_buffer = cx.build_model(|cx| { + Buffer::new(0, cx.entity_id().as_u64(), "const c: usize = 3;\n") .with_language(rust_language, cx) }); - let multibuffer = cx.add_model(|cx| { + let multibuffer = cx.build_model(|cx| { let mut multibuffer = MultiBuffer::new(0); multibuffer.push_excerpts( toml_buffer.clone(), @@ -2432,12 +2409,10 @@ async fn test_delete(cx: &mut gpui::TestAppContext) { fn test_delete_line(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ @@ -2457,12 +2432,10 @@ fn test_delete_line(cx: &mut TestAppContext) { ); }); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)]) @@ -2867,12 +2840,10 @@ async fn test_manipulate_text(cx: &mut TestAppContext) { fn test_duplicate_line(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ @@ -2895,12 +2866,10 @@ fn test_duplicate_line(cx: &mut TestAppContext) { ); }); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ @@ -2924,12 +2893,10 @@ fn test_duplicate_line(cx: &mut TestAppContext) { fn test_move_line_up_down(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.fold_ranges( vec![ @@ -3025,12 +2992,10 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let editor = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); - build_editor(buffer, cx) - }) - .root(cx); + let editor = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); + build_editor(buffer, cx) + }); editor.update(cx, |editor, cx| { let snapshot = editor.buffer.read(cx).snapshot(cx); editor.insert_blocks( @@ -3345,12 +3310,10 @@ async fn test_paste_multiline(cx: &mut gpui::TestAppContext) { fn test_select_all(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.select_all(&SelectAll, cx); assert_eq!( @@ -3364,12 +3327,10 @@ fn test_select_all(cx: &mut TestAppContext) { fn test_select_line(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ @@ -3413,12 +3374,10 @@ fn test_select_line(cx: &mut TestAppContext) { fn test_split_selection_into_lines(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.fold_ranges( vec![ @@ -3486,12 +3445,10 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) { fn test_add_selection_above_below(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let view = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx); - build_editor(buffer, cx) - }) - .root(cx); + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx); + build_editor(buffer, cx) + }); view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { @@ -3786,10 +3743,11 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { "# .unindent(); - let buffer = - cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx)); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| { + Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) + }); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let view = cx.add_window(|cx| build_editor(buffer, cx)); view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; @@ -3950,10 +3908,11 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) { let text = "fn a() {}"; - let buffer = - cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx)); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| { + Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) + }); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let editor = cx.add_window(|cx| build_editor(buffer, cx)); editor .condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx)) .await; @@ -4514,10 +4473,11 @@ async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) { "# .unindent(); - let buffer = - cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx)); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| { + Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) + }); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let view = cx.add_window(|cx| build_editor(buffer, cx)); view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; @@ -4663,10 +4623,11 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) { "# .unindent(); - let buffer = - cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx)); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| { + Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) + }); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let editor = cx.add_window(|cx| build_editor(buffer, cx)); editor .condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; @@ -4756,7 +4717,7 @@ async fn test_snippets(cx: &mut gpui::TestAppContext) { ); let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx)); - let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let editor = cx.add_window(|cx| build_editor(buffer, cx)); editor.update(cx, |editor, cx| { let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap(); @@ -4872,7 +4833,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; @@ -4885,8 +4846,8 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { cx.foreground().start_waiting(); let fake_server = fake_servers.next().await.unwrap(); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let editor = cx.add_window(|cx| build_editor(buffer, cx)); editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); @@ -4984,7 +4945,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; @@ -4997,8 +4958,8 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { cx.foreground().start_waiting(); let fake_server = fake_servers.next().await.unwrap(); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let editor = cx.add_window(|cx| build_editor(buffer, cx)); editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); @@ -5103,7 +5064,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; @@ -5118,8 +5079,8 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) { cx.foreground().start_waiting(); let fake_server = fake_servers.next().await.unwrap(); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let editor = cx.add_window(|cx| build_editor(buffer, cx)); editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); let format = editor.update(cx, |editor, cx| { @@ -5879,8 +5840,9 @@ async fn test_toggle_block_comment(cx: &mut gpui::TestAppContext) { fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, sample_text(3, 4, 'a'))); - let multibuffer = cx.add_model(|cx| { + let buffer = + cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a'))); + let multibuffer = cx.build_model(|cx| { let mut multibuffer = MultiBuffer::new(0); multibuffer.push_excerpts( buffer.clone(), @@ -5900,7 +5862,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) { multibuffer }); - let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx); + let view = cx.add_window(|cx| build_editor(multibuffer, cx)); view.update(cx, |view, cx| { assert_eq!(view.text(cx), "aaaa\nbbbb"); view.change_selections(None, cx, |s| { @@ -5963,14 +5925,14 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) { primary: None, } }); - let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, initial_text)); - let multibuffer = cx.add_model(|cx| { + let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), initial_text)); + let multibuffer = cx.build_model(|cx| { let mut multibuffer = MultiBuffer::new(0); multibuffer.push_excerpts(buffer, excerpt_ranges, cx); multibuffer }); - let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx); + let view = cx.add_window(|cx| build_editor(multibuffer, cx)); view.update(cx, |view, cx| { let (expected_text, selection_ranges) = marked_text_ranges( indoc! {" @@ -6021,9 +5983,10 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) { fn test_refresh_selections(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, sample_text(3, 4, 'a'))); + let buffer = + cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a'))); let mut excerpt1_id = None; - let multibuffer = cx.add_model(|cx| { + let multibuffer = cx.build_model(|cx| { let mut multibuffer = MultiBuffer::new(0); excerpt1_id = multibuffer .push_excerpts( @@ -6046,24 +6009,22 @@ fn test_refresh_selections(cx: &mut TestAppContext) { multibuffer }); - let editor = cx - .add_window(|cx| { - let mut editor = build_editor(multibuffer.clone(), cx); - let snapshot = editor.snapshot(cx); - editor.change_selections(None, cx, |s| { - s.select_ranges([Point::new(1, 3)..Point::new(1, 3)]) - }); - editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx); - assert_eq!( - editor.selections.ranges(cx), - [ - Point::new(1, 3)..Point::new(1, 3), - Point::new(2, 1)..Point::new(2, 1), - ] - ); - editor - }) - .root(cx); + let editor = cx.add_window(|cx| { + let mut editor = build_editor(multibuffer.clone(), cx); + let snapshot = editor.snapshot(cx); + editor.change_selections(None, cx, |s| { + s.select_ranges([Point::new(1, 3)..Point::new(1, 3)]) + }); + editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx); + assert_eq!( + editor.selections.ranges(cx), + [ + Point::new(1, 3)..Point::new(1, 3), + Point::new(2, 1)..Point::new(2, 1), + ] + ); + editor + }); // Refreshing selections is a no-op when excerpts haven't changed. editor.update(cx, |editor, cx| { @@ -6108,9 +6069,10 @@ fn test_refresh_selections(cx: &mut TestAppContext) { fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, sample_text(3, 4, 'a'))); + let buffer = + cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a'))); let mut excerpt1_id = None; - let multibuffer = cx.add_model(|cx| { + let multibuffer = cx.build_model(|cx| { let mut multibuffer = MultiBuffer::new(0); excerpt1_id = multibuffer .push_excerpts( @@ -6133,18 +6095,16 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) { multibuffer }); - let editor = cx - .add_window(|cx| { - let mut editor = build_editor(multibuffer.clone(), cx); - let snapshot = editor.snapshot(cx); - editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx); - assert_eq!( - editor.selections.ranges(cx), - [Point::new(1, 3)..Point::new(1, 3)] - ); - editor - }) - .root(cx); + let editor = cx.add_window(|cx| { + let mut editor = build_editor(multibuffer.clone(), cx); + let snapshot = editor.snapshot(cx); + editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx); + assert_eq!( + editor.selections.ranges(cx), + [Point::new(1, 3)..Point::new(1, 3)] + ); + editor + }); multibuffer.update(cx, |multibuffer, cx| { multibuffer.remove_excerpts([excerpt1_id.unwrap()], cx); @@ -6205,10 +6165,11 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) { "{{} }\n", // ); - let buffer = - cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text).with_language(language, cx)); - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| { + Buffer::new(0, cx.entity_id().as_u64(), text).with_language(language, cx) + }); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let view = cx.add_window(|cx| build_editor(buffer, cx)); view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; @@ -6244,12 +6205,10 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) { fn test_highlighted_ranges(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let editor = cx - .add_window(|cx| { - let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx); - build_editor(buffer.clone(), cx) - }) - .root(cx); + let editor = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx); + build_editor(buffer.clone(), cx) + }); editor.update(cx, |editor, cx| { struct Type1; @@ -6288,7 +6247,7 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) { theme::current(cx).as_ref(), ); // Enforce a consistent ordering based on color without relying on the ordering of the - // highlight's `TypeId` which is non-deterministic. + // highlight's `TypeId` which is non-executor. highlighted_ranges.sort_unstable_by_key(|(_, color)| *color); assert_eq!( highlighted_ranges, @@ -6329,29 +6288,28 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) { async fn test_following(cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; let buffer = project.update(cx, |project, cx| { let buffer = project .create_buffer(&sample_text(16, 8, 'a'), None, cx) .unwrap(); - cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)) + cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)) + }); + let leader = cx.add_window(|cx| build_editor(buffer.clone(), cx)); + let follower = cx.update(|cx| { + cx.add_window( + WindowOptions { + bounds: WindowBounds::Fixed(RectF::from_points( + Point::new(0., 0.), + Point::new(10., 80.), + )), + ..Default::default() + }, + |cx| build_editor(buffer.clone(), cx), + ) }); - let leader = cx - .add_window(|cx| build_editor(buffer.clone(), cx)) - .root(cx); - let follower = cx - .update(|cx| { - cx.add_window( - WindowOptions { - bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))), - ..Default::default() - }, - |cx| build_editor(buffer.clone(), cx), - ) - }) - .root(cx); let is_still_following = Rc::new(RefCell::new(true)); let follower_edit_event_count = Rc::new(RefCell::new(0)); @@ -6369,9 +6327,10 @@ async fn test_following(cx: &mut gpui::TestAppContext) { .detach(); cx.subscribe(&follower, move |_, _, event, cx| { - if Editor::should_unfollow_on_event(event, cx) { + if matches!(event.to_follow_event(), Some(FollowEvent::Unfollow)) { *is_still_following.borrow_mut() = false; } + if let Event::BufferEdited = event { *follower_edit_event_count.borrow_mut() += 1; } @@ -6398,7 +6357,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { // Update the scroll position only leader.update(cx, |leader, cx| { - leader.set_scroll_position(vec2f(1.5, 3.5), cx); + leader.set_scroll_position(Point::new(1.5, 3.5), cx); }); follower .update(cx, |follower, cx| { @@ -6408,7 +6367,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { .unwrap(); assert_eq!( follower.update(cx, |follower, cx| follower.scroll_position(cx)), - vec2f(1.5, 3.5) + Point::new(1.5, 3.5) ); assert_eq!(*is_still_following.borrow(), true); assert_eq!(*follower_edit_event_count.borrow(), 0); @@ -6418,7 +6377,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { leader.update(cx, |leader, cx| { leader.change_selections(None, cx, |s| s.select_ranges([0..0])); leader.request_autoscroll(Autoscroll::newest(), cx); - leader.set_scroll_position(vec2f(1.5, 3.5), cx); + leader.set_scroll_position(Point::new(1.5, 3.5), cx); }); follower .update(cx, |follower, cx| { @@ -6427,7 +6386,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { .await .unwrap(); follower.update(cx, |follower, cx| { - assert_eq!(follower.scroll_position(cx), vec2f(1.5, 0.0)); + assert_eq!(follower.scroll_position(cx), Point::new(1.5, 0.0)); assert_eq!(follower.selections.ranges(cx), vec![0..0]); }); assert_eq!(*is_still_following.borrow(), true); @@ -6468,7 +6427,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { follower.set_scroll_anchor( ScrollAnchor { anchor: top_anchor, - offset: vec2f(0.0, 0.5), + offset: Point::new(0.0, 0.5), }, cx, ); @@ -6480,15 +6439,13 @@ async fn test_following(cx: &mut gpui::TestAppContext) { async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; - let workspace = cx - .add_window(|cx| Workspace::test_new(project.clone(), cx)) - .root(cx); + let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); let leader = pane.update(cx, |_, cx| { - let multibuffer = cx.add_model(|_| MultiBuffer::new(0)); + let multibuffer = cx.build_model(|_| MultiBuffer::new(0)); cx.add_view(|cx| build_editor(multibuffer.clone(), cx)) }); @@ -6678,7 +6635,7 @@ fn test_combine_syntax_and_fuzzy_match_highlights() { 4..5, HighlightStyle { color: Some(Hsla::green()), - weight: Some(fonts::Weight::BOLD), + font_weight: Some(gpui::FontWeight::BOLD), ..Default::default() }, ), @@ -6693,14 +6650,14 @@ fn test_combine_syntax_and_fuzzy_match_highlights() { 6..8, HighlightStyle { color: Some(Hsla::green()), - weight: Some(fonts::Weight::BOLD), + font_weight: Some(gpui::FontWeight::BOLD), ..Default::default() }, ), ( 8..9, HighlightStyle { - weight: Some(fonts::Weight::BOLD), + font_weight: Some(gpui::FontWeight::BOLD), ..Default::default() }, ), @@ -6710,7 +6667,7 @@ fn test_combine_syntax_and_fuzzy_match_highlights() { #[gpui::test] async fn go_to_prev_overlapping_diagnostic( - deterministic: Arc, + executor: BackgroundExecutor, cx: &mut gpui::TestAppContext, ) { init_test(cx, |_| {}); @@ -6765,7 +6722,7 @@ async fn go_to_prev_overlapping_diagnostic( }); }); - deterministic.run_until_parked(); + executor.run_until_parked(); cx.update_editor(|editor, cx| { editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, cx); @@ -6805,7 +6762,7 @@ async fn go_to_prev_overlapping_diagnostic( } #[gpui::test] -async fn go_to_hunk(deterministic: Arc, cx: &mut gpui::TestAppContext) { +async fn go_to_hunk(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); let mut cx = EditorTestContext::new(cx).await; @@ -6840,7 +6797,7 @@ async fn go_to_hunk(deterministic: Arc, cx: &mut gpui::TestAppCon ); cx.set_diff_base(Some(&diff_base)); - deterministic.run_until_parked(); + executor.run_until_parked(); cx.update_editor(|editor, cx| { //Wrap around the bottom of the buffer @@ -7012,7 +6969,7 @@ async fn test_move_to_enclosing_bracket(cx: &mut gpui::TestAppContext) { } #[gpui::test(iterations = 10)] -async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppContext) { +async fn test_copilot(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); let (copilot, copilot_lsp) = Copilot::fake(cx); @@ -7054,7 +7011,7 @@ async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppC }], vec![], ); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { assert!(editor.context_menu_visible()); assert!(!editor.has_active_copilot_suggestion(cx)); @@ -7096,7 +7053,7 @@ async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppC }], vec![], ); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { assert!(!editor.context_menu_visible()); assert!(editor.has_active_copilot_suggestion(cx)); @@ -7129,7 +7086,7 @@ async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppC }], vec![], ); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { assert!(editor.context_menu_visible()); assert!(!editor.has_active_copilot_suggestion(cx)); @@ -7144,7 +7101,7 @@ async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppC // Ensure existing completion is interpolated when inserting again. cx.simulate_keystroke("c"); - deterministic.run_until_parked(); + executor.run_until_parked(); cx.update_editor(|editor, cx| { assert!(!editor.context_menu_visible()); assert!(editor.has_active_copilot_suggestion(cx)); @@ -7162,7 +7119,7 @@ async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppC }], vec![], ); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { assert!(!editor.context_menu_visible()); assert!(editor.has_active_copilot_suggestion(cx)); @@ -7241,7 +7198,7 @@ async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppC ); cx.update_editor(|editor, cx| editor.next_copilot_suggestion(&Default::default(), cx)); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { assert!(editor.has_active_copilot_suggestion(cx)); assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}"); @@ -7263,7 +7220,7 @@ async fn test_copilot(deterministic: Arc, cx: &mut gpui::TestAppC #[gpui::test] async fn test_copilot_completion_invalidation( - deterministic: Arc, + executor: BackgroundExecutor, cx: &mut gpui::TestAppContext, ) { init_test(cx, |_| {}); @@ -7298,7 +7255,7 @@ async fn test_copilot_completion_invalidation( vec![], ); cx.update_editor(|editor, cx| editor.next_copilot_suggestion(&Default::default(), cx)); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { assert!(editor.has_active_copilot_suggestion(cx)); assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n"); @@ -7329,18 +7286,15 @@ async fn test_copilot_completion_invalidation( } #[gpui::test] -async fn test_copilot_multibuffer( - deterministic: Arc, - cx: &mut gpui::TestAppContext, -) { +async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); let (copilot, copilot_lsp) = Copilot::fake(cx); cx.update(|cx| cx.set_global(copilot)); - let buffer_1 = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, "a = 1\nb = 2\n")); - let buffer_2 = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, "c = 3\nd = 4\n")); - let multibuffer = cx.add_model(|cx| { + let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n")); + let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n")); + let multibuffer = cx.build_model(|cx| { let mut multibuffer = MultiBuffer::new(0); multibuffer.push_excerpts( buffer_1.clone(), @@ -7360,7 +7314,7 @@ async fn test_copilot_multibuffer( ); multibuffer }); - let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx); + let editor = cx.add_window(|cx| build_editor(multibuffer, cx)); handle_copilot_completion_request( &copilot_lsp, @@ -7378,7 +7332,7 @@ async fn test_copilot_multibuffer( }); editor.next_copilot_suggestion(&Default::default(), cx); }); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); editor.update(cx, |editor, cx| { assert!(editor.has_active_copilot_suggestion(cx)); assert_eq!( @@ -7420,7 +7374,7 @@ async fn test_copilot_multibuffer( }); // Ensure the new suggestion is displayed when the debounce timeout expires. - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); editor.update(cx, |editor, cx| { assert!(editor.has_active_copilot_suggestion(cx)); assert_eq!( @@ -7432,10 +7386,7 @@ async fn test_copilot_multibuffer( } #[gpui::test] -async fn test_copilot_disabled_globs( - deterministic: Arc, - cx: &mut gpui::TestAppContext, -) { +async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) { init_test(cx, |settings| { settings .copilot @@ -7446,7 +7397,7 @@ async fn test_copilot_disabled_globs( let (copilot, copilot_lsp) = Copilot::fake(cx); cx.update(|cx| cx.set_global(copilot)); - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/test", json!({ @@ -7470,7 +7421,7 @@ async fn test_copilot_disabled_globs( .await .unwrap(); - let multibuffer = cx.add_model(|cx| { + let multibuffer = cx.build_model(|cx| { let mut multibuffer = MultiBuffer::new(0); multibuffer.push_excerpts( private_buffer.clone(), @@ -7490,7 +7441,7 @@ async fn test_copilot_disabled_globs( ); multibuffer }); - let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx); + let editor = cx.add_window(|cx| build_editor(multibuffer, cx)); let mut copilot_requests = copilot_lsp .handle_request::(move |_params, _cx| async move { @@ -7510,7 +7461,7 @@ async fn test_copilot_disabled_globs( editor.next_copilot_suggestion(&Default::default(), cx); }); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); assert!(copilot_requests.try_next().is_err()); editor.update(cx, |editor, cx| { @@ -7520,7 +7471,7 @@ async fn test_copilot_disabled_globs( editor.next_copilot_suggestion(&Default::default(), cx); }); - deterministic.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); + executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); assert!(copilot_requests.try_next().is_ok()); } @@ -7558,7 +7509,7 @@ async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/a", json!({ @@ -7569,9 +7520,7 @@ async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) { .await; let project = Project::test(fs, ["/a".as_ref()], cx).await; project.update(cx, |project, _| project.languages().add(Arc::new(language))); - let workspace = cx - .add_window(|cx| Workspace::test_new(project.clone(), cx)) - .root(cx); + let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let worktree_id = workspace.update(cx, |workspace, cx| { workspace.project().read_with(cx, |project, cx| { project.worktrees(cx).next().unwrap().read(cx).id() @@ -7665,7 +7614,7 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut gpui::Test })) .await; - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/a", json!({ @@ -7982,7 +7931,7 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.background()); + let fs = FakeFs::new(cx.executor()); fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; @@ -7996,8 +7945,8 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) { .unwrap(); let buffer_text = "one\ntwo\nthree\n"; - let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + let editor = cx.add_window(|cx| build_editor(buffer, cx)); editor.update(cx, |editor, cx| editor.set_text(buffer_text, cx)); let format = editor.update(cx, |editor, cx| { @@ -8166,11 +8115,9 @@ pub(crate) fn update_test_project_settings( } pub(crate) fn init_test(cx: &mut TestAppContext, f: fn(&mut AllLanguageSettingsContent)) { - cx.foreground().forbid_parking(); - cx.update(|cx| { cx.set_global(SettingsStore::test(cx)); - theme::init((), cx); + theme::init(cx); client::init_settings(cx); language::init(cx); Project::init_settings(cx); diff --git a/crates/editor2/src/test.rs b/crates/editor2/src/test.rs index 2d3be45a00..ec37c57f2c 100644 --- a/crates/editor2/src/test.rs +++ b/crates/editor2/src/test.rs @@ -60,6 +60,7 @@ pub fn assert_text_with_selections( #[allow(dead_code)] #[cfg(any(test, feature = "test-support"))] pub(crate) fn build_editor(buffer: Model, cx: &mut ViewContext) -> Editor { + // todo!() Editor::new(EditorMode::Full, buffer, None, /*None,*/ cx) } @@ -68,5 +69,6 @@ pub(crate) fn build_editor_with_project( buffer: Model, cx: &mut ViewContext, ) -> Editor { + // todo!() Editor::new(EditorMode::Full, buffer, Some(project), /*None,*/ cx) } diff --git a/crates/editor2/src/test/editor_test_context.rs b/crates/editor2/src/test/editor_test_context.rs index 0ee6b33a2f..304e4fcd2b 100644 --- a/crates/editor2/src/test/editor_test_context.rs +++ b/crates/editor2/src/test/editor_test_context.rs @@ -27,7 +27,7 @@ pub struct EditorTestContext<'a> { impl<'a> EditorTestContext<'a> { pub async fn new(cx: &'a mut gpui::TestAppContext) -> EditorTestContext<'a> { - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); // fs.insert_file("/file", "".to_owned()).await; fs.insert_tree( "/root", diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index f196923ad8..cbee96f037 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -1008,11 +1008,14 @@ impl Context for AppContext { read(entity, self) } - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result { + window: &WindowHandle, + read: impl FnOnce(&T, &AppContext) -> R, + ) -> Result + where + T: 'static, + { let window = self .windows .get(window.id) @@ -1021,7 +1024,11 @@ impl Context for AppContext { .unwrap(); let root_view = window.root_view.clone().unwrap(); - Ok(read(root_view, self)) + let view = root_view + .downcast::() + .map_err(|_| anyhow!("root view's type has changed"))?; + + Ok(read(view.read(self), self)) } } diff --git a/crates/gpui2/src/app/async_context.rs b/crates/gpui2/src/app/async_context.rs index b9eeacb262..0a38d6c76a 100644 --- a/crates/gpui2/src/app/async_context.rs +++ b/crates/gpui2/src/app/async_context.rs @@ -67,11 +67,14 @@ impl Context for AsyncAppContext { lock.update_window(window, f) } - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result { + window: &WindowHandle, + read: impl FnOnce(&T, &AppContext) -> R, + ) -> Result + where + T: 'static, + { let app = self.app.upgrade().context("app was released")?; let lock = app.borrow(); lock.read_window(window, read) @@ -261,11 +264,14 @@ impl Context for AsyncWindowContext { self.app.read_model(handle, read) } - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result { + window: &WindowHandle, + read: impl FnOnce(&T, &AppContext) -> R, + ) -> Result + where + T: 'static, + { self.app.read_window(window, read) } } diff --git a/crates/gpui2/src/app/model_context.rs b/crates/gpui2/src/app/model_context.rs index 1fe9a09ba7..6bc5ba30dd 100644 --- a/crates/gpui2/src/app/model_context.rs +++ b/crates/gpui2/src/app/model_context.rs @@ -1,6 +1,6 @@ use crate::{ AnyView, AnyWindowHandle, AppContext, AsyncAppContext, Context, Effect, Entity, EntityId, - EventEmitter, Model, Subscription, Task, WeakModel, WindowContext, + EventEmitter, Model, Subscription, Task, WeakModel, WindowContext, WindowHandle, }; use anyhow::Result; use derive_more::{Deref, DerefMut}; @@ -240,11 +240,14 @@ impl<'a, T> Context for ModelContext<'a, T> { self.app.read_model(handle, read) } - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result { + window: &WindowHandle, + read: impl FnOnce(&U, &AppContext) -> R, + ) -> Result + where + U: 'static, + { self.app.read_window(window, read) } } diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index f8d5c01160..64895307d2 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -59,11 +59,14 @@ impl Context for TestAppContext { app.read_model(handle, read) } - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result { + window: &WindowHandle, + read: impl FnOnce(&T, &AppContext) -> R, + ) -> Result + where + T: 'static, + { let app = self.app.borrow(); app.read_window(window, read) } @@ -102,8 +105,8 @@ impl TestAppContext { Ok(()) } - pub fn executor(&self) -> &BackgroundExecutor { - &self.background_executor + pub fn executor(&self) -> BackgroundExecutor { + self.background_executor.clone() } pub fn foreground_executor(&self) -> &ForegroundExecutor { diff --git a/crates/gpui2/src/color.rs b/crates/gpui2/src/color.rs index 3ae247962b..c9d7bdc139 100644 --- a/crates/gpui2/src/color.rs +++ b/crates/gpui2/src/color.rs @@ -154,6 +154,30 @@ impl Hsla { pub fn to_rgb(self) -> Rgba { self.into() } + + pub fn red() -> Self { + red() + } + + pub fn green() -> Self { + green() + } + + pub fn blue() -> Self { + blue() + } + + pub fn black() -> Self { + black() + } + + pub fn white() -> Self { + white() + } + + pub fn transparent_black() -> Self { + transparent_black() + } } impl Eq for Hsla {} @@ -212,6 +236,15 @@ pub fn blue() -> Hsla { } } +pub fn green() -> Hsla { + Hsla { + h: 0.3, + s: 1., + l: 0.5, + a: 1., + } +} + impl Hsla { /// Returns true if the HSLA color is fully transparent, false otherwise. pub fn is_transparent(&self) -> bool { diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index ff150824b1..1419010bdd 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -105,11 +105,13 @@ pub trait Context { where F: FnOnce(AnyView, &mut WindowContext<'_>) -> T; - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result; + window: &WindowHandle, + read: impl FnOnce(&T, &AppContext) -> R, + ) -> Result + where + T: 'static; } pub trait VisualContext: Context { diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index a9d2d55453..3e49ffd49b 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -10,7 +10,7 @@ use crate::{ SharedString, Size, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, }; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context as _, Result}; use collections::HashMap; use derive_more::{Deref, DerefMut}; use futures::{ @@ -1429,16 +1429,25 @@ impl Context for WindowContext<'_> { read(&*entity, &*self.app) } - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result { - if window == &self.window.handle { - let root_view = self.window.root_view.clone().unwrap(); - Ok(read(root_view, self)) + window: &WindowHandle, + read: impl FnOnce(&T, &AppContext) -> R, + ) -> Result + where + T: 'static, + { + if window.any_handle == self.window.handle { + let root_view = self + .window + .root_view + .clone() + .unwrap() + .downcast::() + .map_err(|_| anyhow!("the type of the window's root view has changed"))?; + Ok(read(root_view.read(self), self)) } else { - window.read(self.app, read) + self.app.read_window(window, read) } } } @@ -2257,11 +2266,14 @@ impl Context for ViewContext<'_, V> { self.window_cx.read_model(handle, read) } - fn read_window( + fn read_window( &self, - window: &AnyWindowHandle, - read: impl FnOnce(AnyView, &AppContext) -> R, - ) -> Result { + window: &WindowHandle, + read: impl FnOnce(&T, &AppContext) -> R, + ) -> Result + where + T: 'static, + { self.window_cx.read_window(window, read) } } @@ -2335,14 +2347,6 @@ impl WindowHandle { } } - pub fn root(&self, cx: &C) -> Result> { - cx.read_window(&self.any_handle, |root_view, _| { - root_view - .downcast::() - .map_err(|_| anyhow!("the type of the window's root view has changed")) - })? - } - pub fn update( self, cx: &mut C, @@ -2358,6 +2362,29 @@ impl WindowHandle { Ok(cx.update_view(&view, update)) })? } + + pub fn read<'a>(&self, cx: &'a AppContext) -> Result<&'a V> { + let x = cx + .windows + .get(self.id) + .and_then(|window| { + window + .as_ref() + .and_then(|window| window.root_view.clone()) + .map(|root_view| root_view.downcast::()) + }) + .ok_or_else(|| anyhow!("window not found"))? + .map_err(|_| anyhow!("the type of the window's root view has changed"))?; + + Ok(x.read(cx)) + } + + pub fn read_with(self, cx: &C, read_with: impl FnOnce(&V, &AppContext) -> R) -> Result + where + C: Context, + { + cx.read_window(&self, |root_view: &V, cx| read_with(root_view, cx)) + } } impl Copy for WindowHandle {} @@ -2424,11 +2451,16 @@ impl AnyWindowHandle { cx.update_window(self, update) } - pub fn read(self, cx: &C, read: impl FnOnce(AnyView, &AppContext) -> R) -> Result + pub fn read(self, cx: &C, read: impl FnOnce(&T, &AppContext) -> R) -> Result where C: Context, + T: 'static, { - cx.read_window(&self, read) + let view = self + .downcast::() + .context("the type of the window's root view has changed")?; + + cx.read_window(&view, read) } } diff --git a/crates/language2/src/language2.rs b/crates/language2/src/language2.rs index bdea440c08..311049f032 100644 --- a/crates/language2/src/language2.rs +++ b/crates/language2/src/language2.rs @@ -1858,7 +1858,7 @@ mod tests { async fn test_first_line_pattern(cx: &mut TestAppContext) { let mut languages = LanguageRegistry::test(); - languages.set_executor(cx.executor().clone()); + languages.set_executor(cx.executor()); let languages = Arc::new(languages); languages.register( "/javascript", @@ -1895,7 +1895,7 @@ mod tests { #[gpui::test(iterations = 10)] async fn test_language_loading(cx: &mut TestAppContext) { let mut languages = LanguageRegistry::test(); - languages.set_executor(cx.executor().clone()); + languages.set_executor(cx.executor()); let languages = Arc::new(languages); languages.register( "/JSON", diff --git a/crates/prettier2/src/prettier2.rs b/crates/prettier2/src/prettier2.rs index 44151774ae..75cc614eb6 100644 --- a/crates/prettier2/src/prettier2.rs +++ b/crates/prettier2/src/prettier2.rs @@ -490,7 +490,7 @@ mod tests { #[gpui::test] async fn test_prettier_lookup_finds_nothing(cx: &mut gpui::TestAppContext) { - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/root", json!({ @@ -563,7 +563,7 @@ mod tests { #[gpui::test] async fn test_prettier_lookup_in_simple_npm_projects(cx: &mut gpui::TestAppContext) { - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/root", json!({ @@ -628,7 +628,7 @@ mod tests { #[gpui::test] async fn test_prettier_lookup_for_not_installed(cx: &mut gpui::TestAppContext) { - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/root", json!({ @@ -686,7 +686,7 @@ mod tests { #[gpui::test] async fn test_prettier_lookup_in_npm_workspaces(cx: &mut gpui::TestAppContext) { - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/root", json!({ @@ -742,7 +742,7 @@ mod tests { async fn test_prettier_lookup_in_npm_workspaces_for_not_installed( cx: &mut gpui::TestAppContext, ) { - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/root", json!({ diff --git a/crates/project2/src/project2.rs b/crates/project2/src/project2.rs index 95f04dfc82..2cfe6b8d5d 100644 --- a/crates/project2/src/project2.rs +++ b/crates/project2/src/project2.rs @@ -863,7 +863,7 @@ impl Project { cx: &mut gpui::TestAppContext, ) -> Model { let mut languages = LanguageRegistry::test(); - languages.set_executor(cx.executor().clone()); + languages.set_executor(cx.executor()); let http_client = util::http::FakeHttpClient::with_404_response(); let client = cx.update(|cx| client::Client::new(http_client.clone(), cx)); let user_store = cx.build_model(|cx| UserStore::new(client.clone(), http_client, cx)); diff --git a/crates/project2/src/project_tests.rs b/crates/project2/src/project_tests.rs index 19485b2306..97b6ed9c74 100644 --- a/crates/project2/src/project_tests.rs +++ b/crates/project2/src/project_tests.rs @@ -89,7 +89,7 @@ async fn test_symlinks(cx: &mut gpui::TestAppContext) { async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/the-root", json!({ @@ -189,7 +189,7 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/the-root", json!({ @@ -547,7 +547,7 @@ async fn test_reporting_fs_changes_to_language_servers(cx: &mut gpui::TestAppCon })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/the-root", json!({ @@ -734,7 +734,7 @@ async fn test_reporting_fs_changes_to_language_servers(cx: &mut gpui::TestAppCon async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -826,7 +826,7 @@ async fn test_single_file_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { async fn test_hidden_worktrees_diagnostics(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/root", json!({ @@ -914,7 +914,7 @@ async fn test_disk_based_diagnostics_progress(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -1046,7 +1046,7 @@ async fn test_restarting_server_with_diagnostics_running(cx: &mut gpui::TestAppC })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({ "a.rs": "" })).await; let project = Project::test(fs, ["/dir".as_ref()], cx).await; @@ -1125,7 +1125,7 @@ async fn test_restarting_server_with_diagnostics_published(cx: &mut gpui::TestAp })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({ "a.rs": "x" })).await; let project = Project::test(fs, ["/dir".as_ref()], cx).await; @@ -1215,7 +1215,7 @@ async fn test_restarted_server_reporting_invalid_buffer_version(cx: &mut gpui::T })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({ "a.rs": "" })).await; let project = Project::test(fs, ["/dir".as_ref()], cx).await; @@ -1279,7 +1279,7 @@ async fn test_toggling_enable_language_server(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({ "a.rs": "", "b.js": "" })) .await; @@ -1401,7 +1401,7 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { " .unindent(); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({ "a.rs": text })).await; let project = Project::test(fs, ["/dir".as_ref()], cx).await; @@ -1671,7 +1671,7 @@ async fn test_empty_diagnostic_ranges(cx: &mut gpui::TestAppContext) { "let three = 3;\n", ); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({ "a.rs": text })).await; let project = Project::test(fs, ["/dir".as_ref()], cx).await; @@ -1734,7 +1734,7 @@ async fn test_empty_diagnostic_ranges(cx: &mut gpui::TestAppContext) { async fn test_diagnostics_from_multiple_language_servers(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({ "a.rs": "one two three" })) .await; @@ -1813,7 +1813,7 @@ async fn test_edits_from_lsp2_with_past_version(cx: &mut gpui::TestAppContext) { " .unindent(); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -1959,7 +1959,7 @@ async fn test_edits_from_lsp2_with_edits_on_adjacent_lines(cx: &mut gpui::TestAp " .unindent(); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2067,7 +2067,7 @@ async fn test_invalid_edits_from_lsp2(cx: &mut gpui::TestAppContext) { " .unindent(); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2187,7 +2187,7 @@ async fn test_definition(cx: &mut gpui::TestAppContext) { ); let mut fake_servers = language.set_fake_lsp_adapter(Default::default()).await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2299,7 +2299,7 @@ async fn test_completions_without_edit_ranges(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2396,7 +2396,7 @@ async fn test_completions_with_carriage_returns(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2451,7 +2451,7 @@ async fn test_apply_code_actions_with_commands(cx: &mut gpui::TestAppContext) { ); let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2559,7 +2559,7 @@ async fn test_apply_code_actions_with_commands(cx: &mut gpui::TestAppContext) { async fn test_save_file(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2591,7 +2591,7 @@ async fn test_save_file(cx: &mut gpui::TestAppContext) { async fn test_save_in_single_file_worktree(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2622,7 +2622,7 @@ async fn test_save_in_single_file_worktree(cx: &mut gpui::TestAppContext) { async fn test_save_as(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree("/dir", json!({})).await; let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await; @@ -2830,7 +2830,7 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) { async fn test_buffer_identity_across_renames(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2881,7 +2881,7 @@ async fn test_buffer_identity_across_renames(cx: &mut gpui::TestAppContext) { async fn test_buffer_deduping(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -2927,7 +2927,7 @@ async fn test_buffer_deduping(cx: &mut gpui::TestAppContext) { async fn test_buffer_is_dirty(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -3074,7 +3074,7 @@ async fn test_buffer_file_changes_on_disk(cx: &mut gpui::TestAppContext) { init_test(cx); let initial_contents = "aaa\nbbbbb\nc\n"; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -3154,7 +3154,7 @@ async fn test_buffer_file_changes_on_disk(cx: &mut gpui::TestAppContext) { async fn test_buffer_line_endings(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -3216,7 +3216,7 @@ async fn test_buffer_line_endings(cx: &mut gpui::TestAppContext) { async fn test_grouped_diagnostics(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/the-dir", json!({ @@ -3479,7 +3479,7 @@ async fn test_rename(cx: &mut gpui::TestAppContext) { })) .await; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -3596,7 +3596,7 @@ async fn test_rename(cx: &mut gpui::TestAppContext) { async fn test_search(cx: &mut gpui::TestAppContext) { init_test(cx); - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -3655,7 +3655,7 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) { let search_query = "file"; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -3767,7 +3767,7 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) { let search_query = "file"; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ @@ -3878,7 +3878,7 @@ async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContex let search_query = "file"; - let fs = FakeFs::new(cx.executor().clone()); + let fs = FakeFs::new(cx.executor()); fs.insert_tree( "/dir", json!({ diff --git a/crates/rpc2/src/peer.rs b/crates/rpc2/src/peer.rs index 80a2ab4378..20a36efdfe 100644 --- a/crates/rpc2/src/peer.rs +++ b/crates/rpc2/src/peer.rs @@ -577,18 +577,18 @@ mod tests { let client2 = Peer::new(0); let (client1_to_server_conn, server_to_client_1_conn, _kill) = - Connection::in_memory(cx.executor().clone()); + Connection::in_memory(cx.executor()); let (client1_conn_id, io_task1, client1_incoming) = - client1.add_test_connection(client1_to_server_conn, cx.executor().clone()); + client1.add_test_connection(client1_to_server_conn, cx.executor()); let (_, io_task2, server_incoming1) = - server.add_test_connection(server_to_client_1_conn, cx.executor().clone()); + server.add_test_connection(server_to_client_1_conn, cx.executor()); let (client2_to_server_conn, server_to_client_2_conn, _kill) = - Connection::in_memory(cx.executor().clone()); + Connection::in_memory(cx.executor()); let (client2_conn_id, io_task3, client2_incoming) = - client2.add_test_connection(client2_to_server_conn, cx.executor().clone()); + client2.add_test_connection(client2_to_server_conn, cx.executor()); let (_, io_task4, server_incoming2) = - server.add_test_connection(server_to_client_2_conn, cx.executor().clone()); + server.add_test_connection(server_to_client_2_conn, cx.executor()); executor.spawn(io_task1).detach(); executor.spawn(io_task2).detach(); @@ -763,16 +763,16 @@ mod tests { #[gpui::test(iterations = 50)] async fn test_dropping_request_before_completion(cx: &mut TestAppContext) { - let executor = cx.executor().clone(); + let executor = cx.executor(); let server = Peer::new(0); let client = Peer::new(0); let (client_to_server_conn, server_to_client_conn, _kill) = - Connection::in_memory(cx.executor().clone()); + Connection::in_memory(cx.executor()); let (client_to_server_conn_id, io_task1, mut client_incoming) = - client.add_test_connection(client_to_server_conn, cx.executor().clone()); + client.add_test_connection(client_to_server_conn, cx.executor()); let (server_to_client_conn_id, io_task2, mut server_incoming) = - server.add_test_connection(server_to_client_conn, cx.executor().clone()); + server.add_test_connection(server_to_client_conn, cx.executor()); executor.spawn(io_task1).detach(); executor.spawn(io_task2).detach(); diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 24ec810ac5..9514e9e492 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3443,27 +3443,27 @@ impl Workspace { }) } - // todo!() - // #[cfg(any(test, feature = "test-support"))] - // pub fn test_new(project: ModelHandle, cx: &mut ViewContext) -> Self { - // use node_runtime::FakeNodeRuntime; + #[cfg(any(test, feature = "test-support"))] + pub fn test_new(project: Model, cx: &mut ViewContext) -> Self { + use gpui::Context; + use node_runtime::FakeNodeRuntime; - // let client = project.read(cx).client(); - // let user_store = project.read(cx).user_store(); + let client = project.read(cx).client(); + let user_store = project.read(cx).user_store(); - // let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx)); - // let app_state = Arc::new(AppState { - // languages: project.read(cx).languages().clone(), - // workspace_store, - // client, - // user_store, - // fs: project.read(cx).fs().clone(), - // build_window_options: |_, _, _| Default::default(), - // initialize_workspace: |_, _, _, _| Task::ready(Ok(())), - // node_runtime: FakeNodeRuntime::new(), - // }); - // Self::new(0, project, app_state, cx) - // } + let workspace_store = cx.build_model(|cx| WorkspaceStore::new(client.clone(), cx)); + let app_state = Arc::new(AppState { + languages: project.read(cx).languages().clone(), + workspace_store, + client, + user_store, + fs: project.read(cx).fs().clone(), + build_window_options: |_, _, _| Default::default(), + initialize_workspace: |_, _, _, _| Task::ready(Ok(())), + node_runtime: FakeNodeRuntime::new(), + }); + Self::new(0, project, app_state, cx) + } // fn render_dock(&self, position: DockPosition, cx: &WindowContext) -> Option> { // let dock = match position {