Eliminate GPUI View, ViewContext, and WindowContext types (#22632)

There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:

- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`

Not pictured here are the two other failed attempts. It's been quite a
month!

Tasks:

- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs

### issues post merge

- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue



Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
This commit is contained in:
Nathan Sobo 2025-01-25 20:02:45 -07:00 committed by GitHub
parent 21b4a0d50e
commit 6fca1d2b0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
648 changed files with 36248 additions and 28208 deletions

View file

@ -81,14 +81,21 @@ async fn test_host_disconnect(
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
let workspace_b = cx_b
.add_window(|cx| Workspace::new(None, project_b.clone(), client_b.app_state.clone(), cx));
let workspace_b = cx_b.add_window(|window, cx| {
Workspace::new(
None,
project_b.clone(),
client_b.app_state.clone(),
window,
cx,
)
});
let cx_b = &mut VisualTestContext::from_window(*workspace_b, cx_b);
let workspace_b_view = workspace_b.root_view(cx_b).unwrap();
let workspace_b_view = workspace_b.root_model(cx_b).unwrap();
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "b.txt"), None, true, cx)
.update(cx_b, |workspace, window, cx| {
workspace.open_path((worktree_id, "b.txt"), None, true, window, cx)
})
.unwrap()
.await
@ -97,10 +104,10 @@ async fn test_host_disconnect(
.unwrap();
//TODO: focus
assert!(cx_b.update_view(&editor_b, |editor, cx| editor.is_focused(cx)));
editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
assert!(cx_b.update_window_model(&editor_b, |editor, window, _| editor.is_focused(window)));
editor_b.update_in(cx_b, |editor, window, cx| editor.insert("X", window, cx));
cx_b.update(|cx| {
cx_b.update(|_, cx| {
assert!(workspace_b_view.read(cx).is_edited());
});
@ -120,7 +127,7 @@ async fn test_host_disconnect(
// Ensure client B's edited state is reset and that the whole window is blurred.
workspace_b
.update(cx_b, |workspace, cx| {
.update(cx_b, |workspace, _, cx| {
assert!(workspace.active_modal::<DisconnectedOverlay>(cx).is_some());
assert!(!workspace.is_edited());
})
@ -128,8 +135,8 @@ async fn test_host_disconnect(
// Ensure client B is not prompted to save edits when closing window after disconnecting.
let can_close = workspace_b
.update(cx_b, |workspace, cx| {
workspace.prepare_to_close(CloseIntent::Quit, cx)
.update(cx_b, |workspace, window, cx| {
workspace.prepare_to_close(CloseIntent::Quit, window, cx)
})
.unwrap()
.await
@ -200,11 +207,12 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
.await
.unwrap();
let cx_a = cx_a.add_empty_window();
let editor_a = cx_a.new_view(|cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
let editor_a = cx_a
.new_window_model(|window, cx| Editor::for_buffer(buffer_a, Some(project_a), window, cx));
let mut editor_cx_a = EditorTestContext {
cx: cx_a.clone(),
window: cx_a.handle(),
window: cx_a.window_handle(),
editor: editor_a,
assertion_cx: AssertionContextManager::new(),
};
@ -215,11 +223,12 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
.await
.unwrap();
let editor_b = cx_b.new_view(|cx| Editor::for_buffer(buffer_b, Some(project_b), cx));
let editor_b = cx_b
.new_window_model(|window, cx| Editor::for_buffer(buffer_b, Some(project_b), window, cx));
let mut editor_cx_b = EditorTestContext {
cx: cx_b.clone(),
window: cx_b.handle(),
window: cx_b.window_handle(),
editor: editor_b,
assertion_cx: AssertionContextManager::new(),
};
@ -231,8 +240,9 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
editor_cx_b.set_selections_state(indoc! {"
Some textˇ
"});
editor_cx_a
.update_editor(|editor, cx| editor.newline_above(&editor::actions::NewlineAbove, cx));
editor_cx_a.update_editor(|editor, window, cx| {
editor.newline_above(&editor::actions::NewlineAbove, window, cx)
});
executor.run_until_parked();
editor_cx_a.assert_editor_state(indoc! {"
ˇ
@ -252,8 +262,9 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
Some textˇ
"});
editor_cx_a
.update_editor(|editor, cx| editor.newline_below(&editor::actions::NewlineBelow, cx));
editor_cx_a.update_editor(|editor, window, cx| {
editor.newline_below(&editor::actions::NewlineBelow, window, cx)
});
executor.run_until_parked();
editor_cx_a.assert_editor_state(indoc! {"
@ -316,8 +327,9 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
.await
.unwrap();
let cx_b = cx_b.add_empty_window();
let editor_b =
cx_b.new_view(|cx| Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx));
let editor_b = cx_b.new_window_model(|window, cx| {
Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), window, cx)
});
let fake_language_server = fake_language_servers.next().await.unwrap();
cx_a.background_executor.run_until_parked();
@ -327,11 +339,11 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
});
// Type a completion 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);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
editor.handle_input(".", window, cx);
});
cx_b.focus_view(&editor_b);
cx_b.focus(&editor_b);
// Receive a completion request as the host's language server.
// Return some completions from the host's language server.
@ -393,9 +405,9 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
});
// Confirm a completion on the guest.
editor_b.update(cx_b, |editor, cx| {
editor_b.update_in(cx_b, |editor, window, cx| {
assert!(editor.context_menu_visible());
editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx);
editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, window, cx);
assert_eq!(editor.text(cx), "fn main() { a.first_method() }");
});
@ -440,10 +452,10 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
// Now we do a second completion, this time to ensure that documentation/snippets are
// resolved
editor_b.update(cx_b, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges([46..46]));
editor.handle_input("; a", cx);
editor.handle_input(".", cx);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([46..46]));
editor.handle_input("; a", window, cx);
editor.handle_input(".", window, cx);
});
buffer_b.read_with(cx_b, |buffer, _| {
@ -507,18 +519,18 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
completion_response.next().await.unwrap();
editor_b.update(cx_b, |editor, cx| {
editor_b.update_in(cx_b, |editor, window, cx| {
assert!(editor.context_menu_visible());
editor.context_menu_first(&ContextMenuFirst {}, cx);
editor.context_menu_first(&ContextMenuFirst {}, window, cx);
});
resolve_completion_response.next().await.unwrap();
cx_b.executor().run_until_parked();
// When accepting the completion, the snippet is insert.
editor_b.update(cx_b, |editor, cx| {
editor_b.update_in(cx_b, |editor, window, cx| {
assert!(editor.context_menu_visible());
editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx);
editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, window, cx);
assert_eq!(
editor.text(cx),
"use d::SomeTrait;\nfn main() { a.first_method(); a.third_method(, , ) }"
@ -568,8 +580,8 @@ async fn test_collaborating_with_code_actions(
let project_b = client_b.join_remote_project(project_id, cx_b).await;
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@ -592,12 +604,12 @@ async fn test_collaborating_with_code_actions(
requests.next().await;
// Move cursor to a location that contains code actions.
editor_b.update(cx_b, |editor, cx| {
editor.change_selections(None, cx, |s| {
editor_b.update_in(cx_b, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| {
s.select_ranges([Point::new(1, 31)..Point::new(1, 31)])
});
});
cx_b.focus_view(&editor_b);
cx_b.focus(&editor_b);
let mut requests = fake_language_server
.handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
@ -657,11 +669,12 @@ async fn test_collaborating_with_code_actions(
requests.next().await;
// Toggle code actions and wait for them to display.
editor_b.update(cx_b, |editor, cx| {
editor_b.update_in(cx_b, |editor, window, cx| {
editor.toggle_code_actions(
&ToggleCodeActions {
deployed_from_indicator: None,
},
window,
cx,
);
});
@ -673,8 +686,8 @@ async fn test_collaborating_with_code_actions(
// Confirming the code action will trigger a resolve request.
let confirm_action = editor_b
.update(cx_b, |editor, cx| {
Editor::confirm_code_action(editor, &ConfirmCodeAction { item_ix: Some(0) }, cx)
.update_in(cx_b, |editor, window, cx| {
Editor::confirm_code_action(editor, &ConfirmCodeAction { item_ix: Some(0) }, window, cx)
})
.unwrap();
fake_language_server.handle_request::<lsp::request::CodeActionResolveRequest, _, _>(
@ -725,14 +738,14 @@ async fn test_collaborating_with_code_actions(
.downcast::<Editor>()
.unwrap()
});
code_action_editor.update(cx_b, |editor, cx| {
code_action_editor.update_in(cx_b, |editor, window, cx| {
assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
editor.undo(&Undo, cx);
editor.undo(&Undo, window, cx);
assert_eq!(
editor.text(cx),
"mod other;\nfn main() { let foo = other::foo(); }\npub fn foo() -> usize { 4 }"
);
editor.redo(&Redo, cx);
editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
});
}
@ -784,8 +797,8 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "one.rs"), None, true, cx)
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path((worktree_id, "one.rs"), None, true, window, cx)
})
.await
.unwrap()
@ -794,9 +807,9 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
let fake_language_server = fake_language_servers.next().await.unwrap();
// Move cursor to a location that can be renamed.
let prepare_rename = editor_b.update(cx_b, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges([7..7]));
editor.rename(&Rename, cx).unwrap()
let prepare_rename = editor_b.update_in(cx_b, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([7..7]));
editor.rename(&Rename, window, cx).unwrap()
});
fake_language_server
@ -834,12 +847,12 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
});
// Cancel the rename, and repeat the same, but use selections instead of cursor movement
editor_b.update(cx_b, |editor, cx| {
editor.cancel(&editor::actions::Cancel, cx);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.cancel(&editor::actions::Cancel, window, cx);
});
let prepare_rename = editor_b.update(cx_b, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges([7..8]));
editor.rename(&Rename, cx).unwrap()
let prepare_rename = editor_b.update_in(cx_b, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([7..8]));
editor.rename(&Rename, window, cx).unwrap()
});
fake_language_server
@ -875,8 +888,8 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
});
});
let confirm_rename = editor_b.update(cx_b, |editor, cx| {
Editor::confirm_rename(editor, &ConfirmRename, cx).unwrap()
let confirm_rename = editor_b.update_in(cx_b, |editor, window, cx| {
Editor::confirm_rename(editor, &ConfirmRename, window, cx).unwrap()
});
fake_language_server
.handle_request::<lsp::request::Rename, _, _>(|params, _| async move {
@ -934,17 +947,17 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
workspace.active_item_as::<Editor>(cx).unwrap()
});
rename_editor.update(cx_b, |editor, cx| {
rename_editor.update_in(cx_b, |editor, window, cx| {
assert_eq!(
editor.text(cx),
"const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
);
editor.undo(&Undo, cx);
editor.undo(&Undo, window, cx);
assert_eq!(
editor.text(cx),
"const ONE: usize = 1;\nconst TWO: usize = one::ONE + one::ONE;"
);
editor.redo(&Redo, cx);
editor.redo(&Redo, window, cx);
assert_eq!(
editor.text(cx),
"const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
@ -952,12 +965,12 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
});
// Ensure temporary rename edits cannot be undone/redone.
editor_b.update(cx_b, |editor, cx| {
editor.undo(&Undo, cx);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "const ONE: usize = 1;");
editor.undo(&Undo, cx);
editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "const ONE: usize = 1;");
editor.redo(&Redo, cx);
editor.redo(&Redo, window, cx);
assert_eq!(editor.text(cx), "const THREE: usize = 1;");
})
}
@ -1192,7 +1205,8 @@ async fn test_share_project(
.await
.unwrap();
let editor_b = cx_b.new_view(|cx| Editor::for_buffer(buffer_b, None, cx));
let editor_b =
cx_b.new_window_model(|window, cx| Editor::for_buffer(buffer_b, None, window, cx));
// Client A sees client B's selection
executor.run_until_parked();
@ -1206,7 +1220,9 @@ async fn test_share_project(
});
// Edit the buffer as client B and see that edit as client A.
editor_b.update(cx_b, |editor, cx| editor.handle_input("ok, ", cx));
editor_b.update_in(cx_b, |editor, window, cx| {
editor.handle_input("ok, ", window, cx)
});
executor.run_until_parked();
buffer_a.read_with(cx_a, |buffer, _| {
@ -1233,7 +1249,7 @@ async fn test_share_project(
let _project_c = client_c.join_remote_project(initial_project.id, cx_c).await;
// Client B closes the editor, and client A sees client B's selections removed.
cx_b.update(move |_| drop(editor_b));
cx_b.update(move |_, _| drop(editor_b));
executor.run_until_parked();
buffer_a.read_with(cx_a, |buffer, _| {
@ -1297,7 +1313,9 @@ async fn test_on_input_format_from_host_to_guest(
.await
.unwrap();
let cx_a = cx_a.add_empty_window();
let editor_a = cx_a.new_view(|cx| Editor::for_buffer(buffer_a, Some(project_a.clone()), cx));
let editor_a = cx_a.new_window_model(|window, cx| {
Editor::for_buffer(buffer_a, Some(project_a.clone()), window, cx)
});
let fake_language_server = fake_language_servers.next().await.unwrap();
executor.run_until_parked();
@ -1329,10 +1347,10 @@ async fn test_on_input_format_from_host_to_guest(
.unwrap();
// Type a on type formatting trigger character as the guest.
cx_a.focus_view(&editor_a);
editor_a.update(cx_a, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
editor.handle_input(">", cx);
cx_a.focus(&editor_a);
editor_a.update_in(cx_a, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
editor.handle_input(">", window, cx);
});
executor.run_until_parked();
@ -1342,9 +1360,9 @@ async fn test_on_input_format_from_host_to_guest(
});
// Undo should remove LSP edits first
editor_a.update(cx_a, |editor, cx| {
editor_a.update_in(cx_a, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a>~< }");
editor.undo(&Undo, cx);
editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a> }");
});
executor.run_until_parked();
@ -1353,9 +1371,9 @@ async fn test_on_input_format_from_host_to_guest(
assert_eq!(buffer.text(), "fn main() { a> }")
});
editor_a.update(cx_a, |editor, cx| {
editor_a.update_in(cx_a, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a> }");
editor.undo(&Undo, cx);
editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a }");
});
executor.run_until_parked();
@ -1417,16 +1435,18 @@ async fn test_on_input_format_from_guest_to_host(
.await
.unwrap();
let cx_b = cx_b.add_empty_window();
let editor_b = cx_b.new_view(|cx| Editor::for_buffer(buffer_b, Some(project_b.clone()), cx));
let editor_b = cx_b.new_window_model(|window, cx| {
Editor::for_buffer(buffer_b, Some(project_b.clone()), window, 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.
cx_b.focus_view(&editor_b);
editor_b.update(cx_b, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
editor.handle_input(":", cx);
cx_b.focus(&editor_b);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
editor.handle_input(":", window, cx);
});
// Receive an OnTypeFormatting request as the host's language server.
@ -1465,9 +1485,9 @@ async fn test_on_input_format_from_guest_to_host(
});
// Undo should remove LSP edits first
editor_b.update(cx_b, |editor, cx| {
editor_b.update_in(cx_b, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a:~: }");
editor.undo(&Undo, cx);
editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a: }");
});
executor.run_until_parked();
@ -1476,9 +1496,9 @@ async fn test_on_input_format_from_guest_to_host(
assert_eq!(buffer.text(), "fn main() { a: }")
});
editor_b.update(cx_b, |editor, cx| {
editor_b.update_in(cx_b, |editor, window, cx| {
assert_eq!(editor.text(cx), "fn main() { a: }");
editor.undo(&Undo, cx);
editor.undo(&Undo, window, cx);
assert_eq!(editor.text(cx), "fn main() { a }");
});
executor.run_until_parked();
@ -1589,8 +1609,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
.await
.unwrap();
let editor_a = workspace_a
.update(cx_a, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
.update_in(cx_a, |workspace, window, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@ -1639,8 +1659,8 @@ async fn test_mutual_editor_inlay_hint_cache_update(
});
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@ -1657,11 +1677,11 @@ async fn test_mutual_editor_inlay_hint_cache_update(
});
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);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([13..13].clone()));
editor.handle_input(":", window, cx);
});
cx_b.focus_view(&editor_b);
cx_b.focus(&editor_b);
executor.run_until_parked();
editor_a.update(cx_a, |editor, _| {
@ -1678,11 +1698,11 @@ async fn test_mutual_editor_inlay_hint_cache_update(
});
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);
editor_a.update_in(cx_a, |editor, window, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([13..13]));
editor.handle_input("a change to increment both buffers' versions", window, cx);
});
cx_a.focus_view(&editor_a);
cx_a.focus(&editor_a);
executor.run_until_parked();
editor_a.update(cx_a, |editor, _| {
@ -1815,8 +1835,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
cx_a.background_executor.start_waiting();
let editor_a = workspace_a
.update(cx_a, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
.update_in(cx_a, |workspace, window, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@ -1824,8 +1844,8 @@ async fn test_inlay_hint_refresh_is_forwarded(
.unwrap();
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path((worktree_id, "main.rs"), None, true, window, cx)
})
.await
.unwrap()
@ -1985,8 +2005,8 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
// Create editor_a
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
let editor_a = workspace_a
.update(cx_a, |workspace, cx| {
workspace.open_path((worktree_id, "file.txt"), None, true, cx)
.update_in(cx_a, |workspace, window, cx| {
workspace.open_path((worktree_id, "file.txt"), None, true, window, cx)
})
.await
.unwrap()
@ -1997,8 +2017,8 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
let project_b = client_b.join_remote_project(project_id, cx_b).await;
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_b = workspace_b
.update(cx_b, |workspace, cx| {
workspace.open_path((worktree_id, "file.txt"), None, true, cx)
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path((worktree_id, "file.txt"), None, true, window, cx)
})
.await
.unwrap()
@ -2006,9 +2026,9 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
.unwrap();
// client_b now requests git blame for the open buffer
editor_b.update(cx_b, |editor_b, cx| {
editor_b.update_in(cx_b, |editor_b, window, cx| {
assert!(editor_b.blame().is_none());
editor_b.toggle_git_blame(&editor::actions::ToggleGitBlame {}, cx);
editor_b.toggle_git_blame(&editor::actions::ToggleGitBlame {}, window, cx);
});
cx_a.executor().run_until_parked();
@ -2054,7 +2074,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
// editor_b updates the file, which gets sent to client_a, which updates git blame,
// which gets back to client_b.
editor_b.update(cx_b, |editor_b, cx| {
editor_b.update_in(cx_b, |editor_b, _, cx| {
editor_b.edit([(Point::new(0, 3)..Point::new(0, 3), "FOO")], cx);
});
@ -2089,7 +2109,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
});
// Now editor_a also updates the file
editor_a.update(cx_a, |editor_a, cx| {
editor_a.update_in(cx_a, |editor_a, _, cx| {
editor_a.edit([(Point::new(1, 3)..Point::new(1, 3), "FOO")], cx);
});
@ -2175,19 +2195,21 @@ async fn test_collaborating_with_editorconfig(
.await
.unwrap();
let cx_a = cx_a.add_empty_window();
let main_editor_a =
cx_a.new_view(|cx| Editor::for_buffer(main_buffer_a, Some(project_a.clone()), cx));
let other_editor_a =
cx_a.new_view(|cx| Editor::for_buffer(other_buffer_a, Some(project_a), cx));
let main_editor_a = cx_a.new_window_model(|window, cx| {
Editor::for_buffer(main_buffer_a, Some(project_a.clone()), window, cx)
});
let other_editor_a = cx_a.new_window_model(|window, cx| {
Editor::for_buffer(other_buffer_a, Some(project_a), window, cx)
});
let mut main_editor_cx_a = EditorTestContext {
cx: cx_a.clone(),
window: cx_a.handle(),
window: cx_a.window_handle(),
editor: main_editor_a,
assertion_cx: AssertionContextManager::new(),
};
let mut other_editor_cx_a = EditorTestContext {
cx: cx_a.clone(),
window: cx_a.handle(),
window: cx_a.window_handle(),
editor: other_editor_a,
assertion_cx: AssertionContextManager::new(),
};
@ -2207,19 +2229,21 @@ async fn test_collaborating_with_editorconfig(
.await
.unwrap();
let cx_b = cx_b.add_empty_window();
let main_editor_b =
cx_b.new_view(|cx| Editor::for_buffer(main_buffer_b, Some(project_b.clone()), cx));
let other_editor_b =
cx_b.new_view(|cx| Editor::for_buffer(other_buffer_b, Some(project_b.clone()), cx));
let main_editor_b = cx_b.new_window_model(|window, cx| {
Editor::for_buffer(main_buffer_b, Some(project_b.clone()), window, cx)
});
let other_editor_b = cx_b.new_window_model(|window, cx| {
Editor::for_buffer(other_buffer_b, Some(project_b.clone()), window, cx)
});
let mut main_editor_cx_b = EditorTestContext {
cx: cx_b.clone(),
window: cx_b.handle(),
window: cx_b.window_handle(),
editor: main_editor_b,
assertion_cx: AssertionContextManager::new(),
};
let mut other_editor_cx_b = EditorTestContext {
cx: cx_b.clone(),
window: cx_b.handle(),
window: cx_b.window_handle(),
editor: other_editor_b,
assertion_cx: AssertionContextManager::new(),
};
@ -2383,12 +2407,12 @@ fn tab_undo_assert(
cx_b.assert_editor_state(expected_initial);
if a_tabs {
cx_a.update_editor(|editor, cx| {
editor.tab(&editor::actions::Tab, cx);
cx_a.update_editor(|editor, window, cx| {
editor.tab(&editor::actions::Tab, window, cx);
});
} else {
cx_b.update_editor(|editor, cx| {
editor.tab(&editor::actions::Tab, cx);
cx_b.update_editor(|editor, window, cx| {
editor.tab(&editor::actions::Tab, window, cx);
});
}
@ -2399,12 +2423,12 @@ fn tab_undo_assert(
cx_b.assert_editor_state(expected_tabbed);
if a_tabs {
cx_a.update_editor(|editor, cx| {
editor.undo(&editor::actions::Undo, cx);
cx_a.update_editor(|editor, window, cx| {
editor.undo(&editor::actions::Undo, window, cx);
});
} else {
cx_b.update_editor(|editor, cx| {
editor.undo(&editor::actions::Undo, cx);
cx_b.update_editor(|editor, window, cx| {
editor.undo(&editor::actions::Undo, window, cx);
});
}
cx_a.run_until_parked();