Detailed changes
@@ -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
@@ -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",
@@ -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)
@@ -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::<lsp::request::OnTypeFormatting, _, _>(
- |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::<lsp::request::OnTypeFormatting, _, _>(|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::<AllLanguageSettings>(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::<AllLanguageSettings>(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::<Editor>()
- .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::<lsp::request::InlayHintRequest, _, _>(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::<Editor>()
- .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::<lsp::request::InlayHintRefreshRequest>(())
- .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::<AllLanguageSettings>(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::<AllLanguageSettings>(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::<Editor>()
- .unwrap();
-
- let editor_b = workspace_b
- .update(cx_b, |workspace, cx| {
- workspace.open_path((worktree_id, "main.rs"), None, true, cx)
- })
- .await
- .unwrap()
- .downcast::<Editor>()
- .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::<lsp::request::InlayHintRequest, _, _>(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::<lsp::request::InlayHintRefreshRequest>(())
- .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<String> {
- 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
-}
@@ -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(),
@@ -351,28 +351,29 @@ impl Copilot {
}
}
- // #[cfg(any(test, feature = "test-support"))]
- // pub fn fake(cx: &mut gpui::TestAppContext) -> (ModelHandle<Self>, 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)
- // }
+ #[cfg(any(test, feature = "test-support"))]
+ pub fn fake(cx: &mut gpui::TestAppContext) -> (Model<Self>, 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.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,
@@ -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::<Pixels>::zero(), cx);
+ view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::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::<Pixels>::zero(), cx);
+ view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::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::<Pixels>::zero(), cx);
+ view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::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::<Pixels>::zero(), cx);
+ view.update_selection(DisplayPoint::new(0, 0), 0, gpui::Point::<f32>::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::<Pixels>::zero(), cx);
+ view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::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::<Pixels>::zero(), cx);
+ view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::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::<Workspace>::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::<Pixels>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(1, 1),
+ 0,
+ gpui::Point::<Pixels>::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::<Pixels>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(0, 3),
+ 0,
+ gpui::Point::<Pixels>::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)));
@@ -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<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
+ // todo!()
Editor::new(EditorMode::Full, buffer, None, /*None,*/ cx)
}
@@ -68,5 +69,6 @@ pub(crate) fn build_editor_with_project(
buffer: Model<MultiBuffer>,
cx: &mut ViewContext<Editor>,
) -> Editor {
+ // todo!()
Editor::new(EditorMode::Full, buffer, Some(project), /*None,*/ cx)
}
@@ -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",
@@ -1008,11 +1008,14 @@ impl Context for AppContext {
read(entity, self)
}
- fn read_window<R>(
+ fn read_window<T, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R> {
+ window: &WindowHandle<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Result<R>
+ 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::<T>()
+ .map_err(|_| anyhow!("root view's type has changed"))?;
+
+ Ok(read(view.read(self), self))
}
}
@@ -67,11 +67,14 @@ impl Context for AsyncAppContext {
lock.update_window(window, f)
}
- fn read_window<R>(
+ fn read_window<T, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R> {
+ window: &WindowHandle<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Result<R>
+ 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<R>(
+ fn read_window<T, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R> {
+ window: &WindowHandle<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Result<R>
+ where
+ T: 'static,
+ {
self.app.read_window(window, read)
}
}
@@ -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<R>(
+ fn read_window<U, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R> {
+ window: &WindowHandle<U>,
+ read: impl FnOnce(&U, &AppContext) -> R,
+ ) -> Result<R>
+ where
+ U: 'static,
+ {
self.app.read_window(window, read)
}
}
@@ -59,11 +59,14 @@ impl Context for TestAppContext {
app.read_model(handle, read)
}
- fn read_window<R>(
+ fn read_window<T, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R> {
+ window: &WindowHandle<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Result<R>
+ 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 {
@@ -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 {
@@ -105,11 +105,13 @@ pub trait Context {
where
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T;
- fn read_window<R>(
+ fn read_window<T, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R>;
+ window: &WindowHandle<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Result<R>
+ where
+ T: 'static;
}
pub trait VisualContext: Context {
@@ -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<R>(
+ fn read_window<T, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R> {
- if window == &self.window.handle {
- let root_view = self.window.root_view.clone().unwrap();
- Ok(read(root_view, self))
+ window: &WindowHandle<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Result<R>
+ where
+ T: 'static,
+ {
+ if window.any_handle == self.window.handle {
+ let root_view = self
+ .window
+ .root_view
+ .clone()
+ .unwrap()
+ .downcast::<T>()
+ .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<V> Context for ViewContext<'_, V> {
self.window_cx.read_model(handle, read)
}
- fn read_window<R>(
+ fn read_window<T, R>(
&self,
- window: &AnyWindowHandle,
- read: impl FnOnce(AnyView, &AppContext) -> R,
- ) -> Result<R> {
+ window: &WindowHandle<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Result<R>
+ where
+ T: 'static,
+ {
self.window_cx.read_window(window, read)
}
}
@@ -2335,14 +2347,6 @@ impl<V: 'static + Render> WindowHandle<V> {
}
}
- pub fn root<C: Context>(&self, cx: &C) -> Result<View<V>> {
- cx.read_window(&self.any_handle, |root_view, _| {
- root_view
- .downcast::<V>()
- .map_err(|_| anyhow!("the type of the window's root view has changed"))
- })?
- }
-
pub fn update<C, R>(
self,
cx: &mut C,
@@ -2358,6 +2362,29 @@ impl<V: 'static + Render> WindowHandle<V> {
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::<V>())
+ })
+ .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<C, R>(self, cx: &C, read_with: impl FnOnce(&V, &AppContext) -> R) -> Result<R>
+ where
+ C: Context,
+ {
+ cx.read_window(&self, |root_view: &V, cx| read_with(root_view, cx))
+ }
}
impl<V> Copy for WindowHandle<V> {}
@@ -2424,11 +2451,16 @@ impl AnyWindowHandle {
cx.update_window(self, update)
}
- pub fn read<C, R>(self, cx: &C, read: impl FnOnce(AnyView, &AppContext) -> R) -> Result<R>
+ pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(&T, &AppContext) -> R) -> Result<R>
where
C: Context,
+ T: 'static,
{
- cx.read_window(&self, read)
+ let view = self
+ .downcast::<T>()
+ .context("the type of the window's root view has changed")?;
+
+ cx.read_window(&view, read)
}
}
@@ -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",
@@ -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!({
@@ -863,7 +863,7 @@ impl Project {
cx: &mut gpui::TestAppContext,
) -> Model<Project> {
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));
@@ -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!({
@@ -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();
@@ -3443,27 +3443,27 @@ impl Workspace {
})
}
- // todo!()
- // #[cfg(any(test, feature = "test-support"))]
- // pub fn test_new(project: ModelHandle<Project>, cx: &mut ViewContext<Self>) -> Self {
- // use node_runtime::FakeNodeRuntime;
-
- // 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)
- // }
+ #[cfg(any(test, feature = "test-support"))]
+ pub fn test_new(project: Model<Project>, cx: &mut ViewContext<Self>) -> Self {
+ use gpui::Context;
+ use node_runtime::FakeNodeRuntime;
+
+ let client = project.read(cx).client();
+ let user_store = project.read(cx).user_store();
+
+ 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<AnyElement<Self>> {
// let dock = match position {