editor_tests.rs

   1//todo(partially ported)
   2// use std::{
   3//     path::Path,
   4//     sync::{
   5//         atomic::{self, AtomicBool, AtomicUsize},
   6//         Arc,
   7//     },
   8// };
   9
  10// use call::ActiveCall;
  11// use editor::{
  12//     test::editor_test_context::{AssertionContextManager, EditorTestContext},
  13//     Anchor, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, Redo, Rename,
  14//     ToggleCodeActions, Undo,
  15// };
  16// use gpui::{BackgroundExecutor, TestAppContext, VisualContext, VisualTestContext};
  17// use indoc::indoc;
  18// use language::{
  19//     language_settings::{AllLanguageSettings, InlayHintSettings},
  20//     tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig,
  21// };
  22// use rpc::RECEIVE_TIMEOUT;
  23// use serde_json::json;
  24// use settings::SettingsStore;
  25// use text::Point;
  26// use workspace::Workspace;
  27
  28// use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
  29
  30// #[gpui::test(iterations = 10)]
  31// async fn test_host_disconnect(
  32//     executor: BackgroundExecutor,
  33//     cx_a: &mut TestAppContext,
  34//     cx_b: &mut TestAppContext,
  35//     cx_c: &mut TestAppContext,
  36// ) {
  37//     let mut server = TestServer::start(executor).await;
  38//     let client_a = server.create_client(cx_a, "user_a").await;
  39//     let client_b = server.create_client(cx_b, "user_b").await;
  40//     let client_c = server.create_client(cx_c, "user_c").await;
  41//     server
  42//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)])
  43//         .await;
  44
  45//     cx_b.update(editor::init);
  46
  47//     client_a
  48//         .fs()
  49//         .insert_tree(
  50//             "/a",
  51//             serde_json::json!({
  52//                 "a.txt": "a-contents",
  53//                 "b.txt": "b-contents",
  54//             }),
  55//         )
  56//         .await;
  57
  58//     let active_call_a = cx_a.read(ActiveCall::global);
  59//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
  60
  61//     let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees().next().unwrap());
  62//     let project_id = active_call_a
  63//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
  64//         .await
  65//         .unwrap();
  66
  67//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
  68//     executor.run_until_parked();
  69
  70//     assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
  71
  72//     let workspace_b =
  73//         cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
  74//     let cx_b = &mut VisualTestContext::from_window(*workspace_b, cx_b);
  75
  76//     let editor_b = workspace_b
  77//         .update(cx_b, |workspace, cx| {
  78//             workspace.open_path((worktree_id, "b.txt"), None, true, cx)
  79//         })
  80//         .unwrap()
  81//         .await
  82//         .unwrap()
  83//         .downcast::<Editor>()
  84//         .unwrap();
  85
  86//     //TODO: focus
  87//     assert!(cx_b.update_view(&editor_b, |editor, cx| editor.is_focused(cx)));
  88//     editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
  89//     //todo(is_edited)
  90//     // assert!(workspace_b.is_edited(cx_b));
  91
  92//     // Drop client A's connection. Collaborators should disappear and the project should not be shown as shared.
  93//     server.forbid_connections();
  94//     server.disconnect_client(client_a.peer_id().unwrap());
  95//     executor.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
  96
  97//     project_a.read_with(cx_a, |project, _| project.collaborators().is_empty());
  98
  99//     project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
 100
 101//     project_b.read_with(cx_b, |project, _| project.is_read_only());
 102
 103//     assert!(worktree_a.read_with(cx_a, |tree, _| !tree.as_local().unwrap().is_shared()));
 104
 105//     // Ensure client B's edited state is reset and that the whole window is blurred.
 106
 107//     workspace_b.update(cx_b, |_, cx| {
 108//         assert_eq!(cx.focused_view_id(), None);
 109//     });
 110//     // assert!(!workspace_b.is_edited(cx_b));
 111
 112//     // Ensure client B is not prompted to save edits when closing window after disconnecting.
 113//     let can_close = workspace_b
 114//         .update(cx_b, |workspace, cx| workspace.prepare_to_close(true, cx))
 115//         .await
 116//         .unwrap();
 117//     assert!(can_close);
 118
 119//     // Allow client A to reconnect to the server.
 120//     server.allow_connections();
 121//     executor.advance_clock(RECEIVE_TIMEOUT);
 122
 123//     // Client B calls client A again after they reconnected.
 124//     let active_call_b = cx_b.read(ActiveCall::global);
 125//     active_call_b
 126//         .update(cx_b, |call, cx| {
 127//             call.invite(client_a.user_id().unwrap(), None, cx)
 128//         })
 129//         .await
 130//         .unwrap();
 131//     executor.run_until_parked();
 132//     active_call_a
 133//         .update(cx_a, |call, cx| call.accept_incoming(cx))
 134//         .await
 135//         .unwrap();
 136
 137//     active_call_a
 138//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 139//         .await
 140//         .unwrap();
 141
 142//     // Drop client A's connection again. We should still unshare it successfully.
 143//     server.forbid_connections();
 144//     server.disconnect_client(client_a.peer_id().unwrap());
 145//     executor.advance_clock(RECEIVE_TIMEOUT + RECONNECT_TIMEOUT);
 146
 147//     project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
 148// }
 149
 150// #[gpui::test]
 151// async fn test_newline_above_or_below_does_not_move_guest_cursor(
 152//     executor: BackgroundExecutor,
 153//     cx_a: &mut TestAppContext,
 154//     cx_b: &mut TestAppContext,
 155// ) {
 156//     let mut server = TestServer::start(&executor).await;
 157//     let client_a = server.create_client(cx_a, "user_a").await;
 158//     let client_b = server.create_client(cx_b, "user_b").await;
 159//     server
 160//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
 161//         .await;
 162//     let active_call_a = cx_a.read(ActiveCall::global);
 163
 164//     client_a
 165//         .fs()
 166//         .insert_tree("/dir", json!({ "a.txt": "Some text\n" }))
 167//         .await;
 168//     let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
 169//     let project_id = active_call_a
 170//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 171//         .await
 172//         .unwrap();
 173
 174//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
 175
 176//     // Open a buffer as client A
 177//     let buffer_a = project_a
 178//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
 179//         .await
 180//         .unwrap();
 181//     let window_a = cx_a.add_empty_window();
 182//     let editor_a =
 183//         window_a.build_view(cx_a, |cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
 184//     let mut editor_cx_a = EditorTestContext {
 185//         cx: cx_a,
 186//         window: window_a.into(),
 187//         editor: editor_a,
 188//         assertion_cx: AssertionContextManager::new(),
 189//     };
 190
 191//     // Open a buffer as client B
 192//     let buffer_b = project_b
 193//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
 194//         .await
 195//         .unwrap();
 196//     let window_b = cx_b.add_empty_window();
 197//     let editor_b =
 198//         window_b.build_view(cx_b, |cx| Editor::for_buffer(buffer_b, Some(project_b), cx));
 199//     let mut editor_cx_b = EditorTestContext {
 200//         cx: cx_b,
 201//         window: window_b.into(),
 202//         editor: editor_b,
 203//         assertion_cx: AssertionContextManager::new(),
 204//     };
 205
 206//     // Test newline above
 207//     editor_cx_a.set_selections_state(indoc! {"
 208//         Some textˇ
 209//     "});
 210//     editor_cx_b.set_selections_state(indoc! {"
 211//         Some textˇ
 212//     "});
 213//     editor_cx_a.update_editor(|editor, cx| editor.newline_above(&editor::NewlineAbove, cx));
 214//     executor.run_until_parked();
 215//     editor_cx_a.assert_editor_state(indoc! {"
 216//         ˇ
 217//         Some text
 218//     "});
 219//     editor_cx_b.assert_editor_state(indoc! {"
 220
 221//         Some textˇ
 222//     "});
 223
 224//     // Test newline below
 225//     editor_cx_a.set_selections_state(indoc! {"
 226
 227//         Some textˇ
 228//     "});
 229//     editor_cx_b.set_selections_state(indoc! {"
 230
 231//         Some textˇ
 232//     "});
 233//     editor_cx_a.update_editor(|editor, cx| editor.newline_below(&editor::NewlineBelow, cx));
 234//     executor.run_until_parked();
 235//     editor_cx_a.assert_editor_state(indoc! {"
 236
 237//         Some text
 238//         ˇ
 239//     "});
 240//     editor_cx_b.assert_editor_state(indoc! {"
 241
 242//         Some textˇ
 243
 244//     "});
 245// }
 246
 247// #[gpui::test(iterations = 10)]
 248// async fn test_collaborating_with_completion(
 249//     executor: BackgroundExecutor,
 250//     cx_a: &mut TestAppContext,
 251//     cx_b: &mut TestAppContext,
 252// ) {
 253//     let mut server = TestServer::start(&executor).await;
 254//     let client_a = server.create_client(cx_a, "user_a").await;
 255//     let client_b = server.create_client(cx_b, "user_b").await;
 256//     server
 257//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
 258//         .await;
 259//     let active_call_a = cx_a.read(ActiveCall::global);
 260
 261//     // Set up a fake language server.
 262//     let mut language = Language::new(
 263//         LanguageConfig {
 264//             name: "Rust".into(),
 265//             path_suffixes: vec!["rs".to_string()],
 266//             ..Default::default()
 267//         },
 268//         Some(tree_sitter_rust::language()),
 269//     );
 270//     let mut fake_language_servers = language
 271//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 272//             capabilities: lsp::ServerCapabilities {
 273//                 completion_provider: Some(lsp::CompletionOptions {
 274//                     trigger_characters: Some(vec![".".to_string()]),
 275//                     resolve_provider: Some(true),
 276//                     ..Default::default()
 277//                 }),
 278//                 ..Default::default()
 279//             },
 280//             ..Default::default()
 281//         }))
 282//         .await;
 283//     client_a.language_registry().add(Arc::new(language));
 284
 285//     client_a
 286//         .fs()
 287//         .insert_tree(
 288//             "/a",
 289//             json!({
 290//                 "main.rs": "fn main() { a }",
 291//                 "other.rs": "",
 292//             }),
 293//         )
 294//         .await;
 295//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
 296//     let project_id = active_call_a
 297//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 298//         .await
 299//         .unwrap();
 300//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
 301
 302//     // Open a file in an editor as the guest.
 303//     let buffer_b = project_b
 304//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
 305//         .await
 306//         .unwrap();
 307//     let window_b = cx_b.add_empty_window();
 308//     let editor_b = window_b.build_view(cx_b, |cx| {
 309//         Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
 310//     });
 311
 312//     let fake_language_server = fake_language_servers.next().await.unwrap();
 313//     cx_a.foreground().run_until_parked();
 314
 315//     buffer_b.read_with(cx_b, |buffer, _| {
 316//         assert!(!buffer.completion_triggers().is_empty())
 317//     });
 318
 319//     // Type a completion trigger character as the guest.
 320//     editor_b.update(cx_b, |editor, cx| {
 321//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
 322//         editor.handle_input(".", cx);
 323//         cx.focus(&editor_b);
 324//     });
 325
 326//     // Receive a completion request as the host's language server.
 327//     // Return some completions from the host's language server.
 328//     cx_a.foreground().start_waiting();
 329//     fake_language_server
 330//         .handle_request::<lsp::request::Completion, _, _>(|params, _| async move {
 331//             assert_eq!(
 332//                 params.text_document_position.text_document.uri,
 333//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
 334//             );
 335//             assert_eq!(
 336//                 params.text_document_position.position,
 337//                 lsp::Position::new(0, 14),
 338//             );
 339
 340//             Ok(Some(lsp::CompletionResponse::Array(vec![
 341//                 lsp::CompletionItem {
 342//                     label: "first_method(…)".into(),
 343//                     detail: Some("fn(&mut self, B) -> C".into()),
 344//                     text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 345//                         new_text: "first_method($1)".to_string(),
 346//                         range: lsp::Range::new(
 347//                             lsp::Position::new(0, 14),
 348//                             lsp::Position::new(0, 14),
 349//                         ),
 350//                     })),
 351//                     insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
 352//                     ..Default::default()
 353//                 },
 354//                 lsp::CompletionItem {
 355//                     label: "second_method(…)".into(),
 356//                     detail: Some("fn(&mut self, C) -> D<E>".into()),
 357//                     text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 358//                         new_text: "second_method()".to_string(),
 359//                         range: lsp::Range::new(
 360//                             lsp::Position::new(0, 14),
 361//                             lsp::Position::new(0, 14),
 362//                         ),
 363//                     })),
 364//                     insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
 365//                     ..Default::default()
 366//                 },
 367//             ])))
 368//         })
 369//         .next()
 370//         .await
 371//         .unwrap();
 372//     cx_a.foreground().finish_waiting();
 373
 374//     // Open the buffer on the host.
 375//     let buffer_a = project_a
 376//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
 377//         .await
 378//         .unwrap();
 379//     cx_a.foreground().run_until_parked();
 380
 381//     buffer_a.read_with(cx_a, |buffer, _| {
 382//         assert_eq!(buffer.text(), "fn main() { a. }")
 383//     });
 384
 385//     // Confirm a completion on the guest.
 386
 387//     editor_b.read_with(cx_b, |editor, _| assert!(editor.context_menu_visible()));
 388//     editor_b.update(cx_b, |editor, cx| {
 389//         editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx);
 390//         assert_eq!(editor.text(cx), "fn main() { a.first_method() }");
 391//     });
 392
 393//     // Return a resolved completion from the host's language server.
 394//     // The resolved completion has an additional text edit.
 395//     fake_language_server.handle_request::<lsp::request::ResolveCompletionItem, _, _>(
 396//         |params, _| async move {
 397//             assert_eq!(params.label, "first_method(…)");
 398//             Ok(lsp::CompletionItem {
 399//                 label: "first_method(…)".into(),
 400//                 detail: Some("fn(&mut self, B) -> C".into()),
 401//                 text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 402//                     new_text: "first_method($1)".to_string(),
 403//                     range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
 404//                 })),
 405//                 additional_text_edits: Some(vec![lsp::TextEdit {
 406//                     new_text: "use d::SomeTrait;\n".to_string(),
 407//                     range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 0)),
 408//                 }]),
 409//                 insert_text_format: Some(lsp::InsertTextFormat::SNIPPET),
 410//                 ..Default::default()
 411//             })
 412//         },
 413//     );
 414
 415//     // The additional edit is applied.
 416//     cx_a.executor().run_until_parked();
 417
 418//     buffer_a.read_with(cx_a, |buffer, _| {
 419//         assert_eq!(
 420//             buffer.text(),
 421//             "use d::SomeTrait;\nfn main() { a.first_method() }"
 422//         );
 423//     });
 424
 425//     buffer_b.read_with(cx_b, |buffer, _| {
 426//         assert_eq!(
 427//             buffer.text(),
 428//             "use d::SomeTrait;\nfn main() { a.first_method() }"
 429//         );
 430//     });
 431// }
 432
 433// #[gpui::test(iterations = 10)]
 434// async fn test_collaborating_with_code_actions(
 435//     executor: BackgroundExecutor,
 436//     cx_a: &mut TestAppContext,
 437//     cx_b: &mut TestAppContext,
 438// ) {
 439//     let mut server = TestServer::start(&executor).await;
 440//     let client_a = server.create_client(cx_a, "user_a").await;
 441//     //
 442//     let client_b = server.create_client(cx_b, "user_b").await;
 443//     server
 444//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
 445//         .await;
 446//     let active_call_a = cx_a.read(ActiveCall::global);
 447
 448//     cx_b.update(editor::init);
 449
 450//     // Set up a fake language server.
 451//     let mut language = Language::new(
 452//         LanguageConfig {
 453//             name: "Rust".into(),
 454//             path_suffixes: vec!["rs".to_string()],
 455//             ..Default::default()
 456//         },
 457//         Some(tree_sitter_rust::language()),
 458//     );
 459//     let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()).await;
 460//     client_a.language_registry().add(Arc::new(language));
 461
 462//     client_a
 463//         .fs()
 464//         .insert_tree(
 465//             "/a",
 466//             json!({
 467//                 "main.rs": "mod other;\nfn main() { let foo = other::foo(); }",
 468//                 "other.rs": "pub fn foo() -> usize { 4 }",
 469//             }),
 470//         )
 471//         .await;
 472//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
 473//     let project_id = active_call_a
 474//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 475//         .await
 476//         .unwrap();
 477
 478//     // Join the project as client B.
 479//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
 480//     let window_b =
 481//         cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
 482//     let workspace_b = window_b.root(cx_b);
 483//     let editor_b = workspace_b
 484//         .update(cx_b, |workspace, cx| {
 485//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
 486//         })
 487//         .await
 488//         .unwrap()
 489//         .downcast::<Editor>()
 490//         .unwrap();
 491
 492//     let mut fake_language_server = fake_language_servers.next().await.unwrap();
 493//     let mut requests = fake_language_server
 494//         .handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
 495//             assert_eq!(
 496//                 params.text_document.uri,
 497//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
 498//             );
 499//             assert_eq!(params.range.start, lsp::Position::new(0, 0));
 500//             assert_eq!(params.range.end, lsp::Position::new(0, 0));
 501//             Ok(None)
 502//         });
 503//     executor.advance_clock(editor::CODE_ACTIONS_DEBOUNCE_TIMEOUT * 2);
 504//     requests.next().await;
 505
 506//     // Move cursor to a location that contains code actions.
 507//     editor_b.update(cx_b, |editor, cx| {
 508//         editor.change_selections(None, cx, |s| {
 509//             s.select_ranges([Point::new(1, 31)..Point::new(1, 31)])
 510//         });
 511//         cx.focus(&editor_b);
 512//     });
 513
 514//     let mut requests = fake_language_server
 515//         .handle_request::<lsp::request::CodeActionRequest, _, _>(|params, _| async move {
 516//             assert_eq!(
 517//                 params.text_document.uri,
 518//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
 519//             );
 520//             assert_eq!(params.range.start, lsp::Position::new(1, 31));
 521//             assert_eq!(params.range.end, lsp::Position::new(1, 31));
 522
 523//             Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction(
 524//                 lsp::CodeAction {
 525//                     title: "Inline into all callers".to_string(),
 526//                     edit: Some(lsp::WorkspaceEdit {
 527//                         changes: Some(
 528//                             [
 529//                                 (
 530//                                     lsp::Url::from_file_path("/a/main.rs").unwrap(),
 531//                                     vec![lsp::TextEdit::new(
 532//                                         lsp::Range::new(
 533//                                             lsp::Position::new(1, 22),
 534//                                             lsp::Position::new(1, 34),
 535//                                         ),
 536//                                         "4".to_string(),
 537//                                     )],
 538//                                 ),
 539//                                 (
 540//                                     lsp::Url::from_file_path("/a/other.rs").unwrap(),
 541//                                     vec![lsp::TextEdit::new(
 542//                                         lsp::Range::new(
 543//                                             lsp::Position::new(0, 0),
 544//                                             lsp::Position::new(0, 27),
 545//                                         ),
 546//                                         "".to_string(),
 547//                                     )],
 548//                                 ),
 549//                             ]
 550//                             .into_iter()
 551//                             .collect(),
 552//                         ),
 553//                         ..Default::default()
 554//                     }),
 555//                     data: Some(json!({
 556//                         "codeActionParams": {
 557//                             "range": {
 558//                                 "start": {"line": 1, "column": 31},
 559//                                 "end": {"line": 1, "column": 31},
 560//                             }
 561//                         }
 562//                     })),
 563//                     ..Default::default()
 564//                 },
 565//             )]))
 566//         });
 567//     executor.advance_clock(editor::CODE_ACTIONS_DEBOUNCE_TIMEOUT * 2);
 568//     requests.next().await;
 569
 570//     // Toggle code actions and wait for them to display.
 571//     editor_b.update(cx_b, |editor, cx| {
 572//         editor.toggle_code_actions(
 573//             &ToggleCodeActions {
 574//                 deployed_from_indicator: false,
 575//             },
 576//             cx,
 577//         );
 578//     });
 579//     cx_a.foreground().run_until_parked();
 580
 581//     editor_b.read_with(cx_b, |editor, _| assert!(editor.context_menu_visible()));
 582
 583//     fake_language_server.remove_request_handler::<lsp::request::CodeActionRequest>();
 584
 585//     // Confirming the code action will trigger a resolve request.
 586//     let confirm_action = workspace_b
 587//         .update(cx_b, |workspace, cx| {
 588//             Editor::confirm_code_action(workspace, &ConfirmCodeAction { item_ix: Some(0) }, cx)
 589//         })
 590//         .unwrap();
 591//     fake_language_server.handle_request::<lsp::request::CodeActionResolveRequest, _, _>(
 592//         |_, _| async move {
 593//             Ok(lsp::CodeAction {
 594//                 title: "Inline into all callers".to_string(),
 595//                 edit: Some(lsp::WorkspaceEdit {
 596//                     changes: Some(
 597//                         [
 598//                             (
 599//                                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
 600//                                 vec![lsp::TextEdit::new(
 601//                                     lsp::Range::new(
 602//                                         lsp::Position::new(1, 22),
 603//                                         lsp::Position::new(1, 34),
 604//                                     ),
 605//                                     "4".to_string(),
 606//                                 )],
 607//                             ),
 608//                             (
 609//                                 lsp::Url::from_file_path("/a/other.rs").unwrap(),
 610//                                 vec![lsp::TextEdit::new(
 611//                                     lsp::Range::new(
 612//                                         lsp::Position::new(0, 0),
 613//                                         lsp::Position::new(0, 27),
 614//                                     ),
 615//                                     "".to_string(),
 616//                                 )],
 617//                             ),
 618//                         ]
 619//                         .into_iter()
 620//                         .collect(),
 621//                     ),
 622//                     ..Default::default()
 623//                 }),
 624//                 ..Default::default()
 625//             })
 626//         },
 627//     );
 628
 629//     // After the action is confirmed, an editor containing both modified files is opened.
 630//     confirm_action.await.unwrap();
 631
 632//     let code_action_editor = workspace_b.read_with(cx_b, |workspace, cx| {
 633//         workspace
 634//             .active_item(cx)
 635//             .unwrap()
 636//             .downcast::<Editor>()
 637//             .unwrap()
 638//     });
 639//     code_action_editor.update(cx_b, |editor, cx| {
 640//         assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
 641//         editor.undo(&Undo, cx);
 642//         assert_eq!(
 643//             editor.text(cx),
 644//             "mod other;\nfn main() { let foo = other::foo(); }\npub fn foo() -> usize { 4 }"
 645//         );
 646//         editor.redo(&Redo, cx);
 647//         assert_eq!(editor.text(cx), "mod other;\nfn main() { let foo = 4; }\n");
 648//     });
 649// }
 650
 651// #[gpui::test(iterations = 10)]
 652// async fn test_collaborating_with_renames(
 653//     executor: BackgroundExecutor,
 654//     cx_a: &mut TestAppContext,
 655//     cx_b: &mut TestAppContext,
 656// ) {
 657//     let mut server = TestServer::start(&executor).await;
 658//     let client_a = server.create_client(cx_a, "user_a").await;
 659//     let client_b = server.create_client(cx_b, "user_b").await;
 660//     server
 661//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
 662//         .await;
 663//     let active_call_a = cx_a.read(ActiveCall::global);
 664
 665//     cx_b.update(editor::init);
 666
 667//     // Set up a fake language server.
 668//     let mut language = Language::new(
 669//         LanguageConfig {
 670//             name: "Rust".into(),
 671//             path_suffixes: vec!["rs".to_string()],
 672//             ..Default::default()
 673//         },
 674//         Some(tree_sitter_rust::language()),
 675//     );
 676//     let mut fake_language_servers = language
 677//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 678//             capabilities: lsp::ServerCapabilities {
 679//                 rename_provider: Some(lsp::OneOf::Right(lsp::RenameOptions {
 680//                     prepare_provider: Some(true),
 681//                     work_done_progress_options: Default::default(),
 682//                 })),
 683//                 ..Default::default()
 684//             },
 685//             ..Default::default()
 686//         }))
 687//         .await;
 688//     client_a.language_registry().add(Arc::new(language));
 689
 690//     client_a
 691//         .fs()
 692//         .insert_tree(
 693//             "/dir",
 694//             json!({
 695//                 "one.rs": "const ONE: usize = 1;",
 696//                 "two.rs": "const TWO: usize = one::ONE + one::ONE;"
 697//             }),
 698//         )
 699//         .await;
 700//     let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
 701//     let project_id = active_call_a
 702//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 703//         .await
 704//         .unwrap();
 705//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
 706
 707//     let window_b =
 708//         cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
 709//     let workspace_b = window_b.root(cx_b);
 710//     let editor_b = workspace_b
 711//         .update(cx_b, |workspace, cx| {
 712//             workspace.open_path((worktree_id, "one.rs"), None, true, cx)
 713//         })
 714//         .await
 715//         .unwrap()
 716//         .downcast::<Editor>()
 717//         .unwrap();
 718//     let fake_language_server = fake_language_servers.next().await.unwrap();
 719
 720//     // Move cursor to a location that can be renamed.
 721//     let prepare_rename = editor_b.update(cx_b, |editor, cx| {
 722//         editor.change_selections(None, cx, |s| s.select_ranges([7..7]));
 723//         editor.rename(&Rename, cx).unwrap()
 724//     });
 725
 726//     fake_language_server
 727//         .handle_request::<lsp::request::PrepareRenameRequest, _, _>(|params, _| async move {
 728//             assert_eq!(params.text_document.uri.as_str(), "file:///dir/one.rs");
 729//             assert_eq!(params.position, lsp::Position::new(0, 7));
 730//             Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
 731//                 lsp::Position::new(0, 6),
 732//                 lsp::Position::new(0, 9),
 733//             ))))
 734//         })
 735//         .next()
 736//         .await
 737//         .unwrap();
 738//     prepare_rename.await.unwrap();
 739//     editor_b.update(cx_b, |editor, cx| {
 740//         use editor::ToOffset;
 741//         let rename = editor.pending_rename().unwrap();
 742//         let buffer = editor.buffer().read(cx).snapshot(cx);
 743//         assert_eq!(
 744//             rename.range.start.to_offset(&buffer)..rename.range.end.to_offset(&buffer),
 745//             6..9
 746//         );
 747//         rename.editor.update(cx, |rename_editor, cx| {
 748//             rename_editor.buffer().update(cx, |rename_buffer, cx| {
 749//                 rename_buffer.edit([(0..3, "THREE")], None, cx);
 750//             });
 751//         });
 752//     });
 753
 754//     let confirm_rename = workspace_b.update(cx_b, |workspace, cx| {
 755//         Editor::confirm_rename(workspace, &ConfirmRename, cx).unwrap()
 756//     });
 757//     fake_language_server
 758//         .handle_request::<lsp::request::Rename, _, _>(|params, _| async move {
 759//             assert_eq!(
 760//                 params.text_document_position.text_document.uri.as_str(),
 761//                 "file:///dir/one.rs"
 762//             );
 763//             assert_eq!(
 764//                 params.text_document_position.position,
 765//                 lsp::Position::new(0, 6)
 766//             );
 767//             assert_eq!(params.new_name, "THREE");
 768//             Ok(Some(lsp::WorkspaceEdit {
 769//                 changes: Some(
 770//                     [
 771//                         (
 772//                             lsp::Url::from_file_path("/dir/one.rs").unwrap(),
 773//                             vec![lsp::TextEdit::new(
 774//                                 lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)),
 775//                                 "THREE".to_string(),
 776//                             )],
 777//                         ),
 778//                         (
 779//                             lsp::Url::from_file_path("/dir/two.rs").unwrap(),
 780//                             vec![
 781//                                 lsp::TextEdit::new(
 782//                                     lsp::Range::new(
 783//                                         lsp::Position::new(0, 24),
 784//                                         lsp::Position::new(0, 27),
 785//                                     ),
 786//                                     "THREE".to_string(),
 787//                                 ),
 788//                                 lsp::TextEdit::new(
 789//                                     lsp::Range::new(
 790//                                         lsp::Position::new(0, 35),
 791//                                         lsp::Position::new(0, 38),
 792//                                     ),
 793//                                     "THREE".to_string(),
 794//                                 ),
 795//                             ],
 796//                         ),
 797//                     ]
 798//                     .into_iter()
 799//                     .collect(),
 800//                 ),
 801//                 ..Default::default()
 802//             }))
 803//         })
 804//         .next()
 805//         .await
 806//         .unwrap();
 807//     confirm_rename.await.unwrap();
 808
 809//     let rename_editor = workspace_b.read_with(cx_b, |workspace, cx| {
 810//         workspace
 811//             .active_item(cx)
 812//             .unwrap()
 813//             .downcast::<Editor>()
 814//             .unwrap()
 815//     });
 816//     rename_editor.update(cx_b, |editor, cx| {
 817//         assert_eq!(
 818//             editor.text(cx),
 819//             "const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
 820//         );
 821//         editor.undo(&Undo, cx);
 822//         assert_eq!(
 823//             editor.text(cx),
 824//             "const ONE: usize = 1;\nconst TWO: usize = one::ONE + one::ONE;"
 825//         );
 826//         editor.redo(&Redo, cx);
 827//         assert_eq!(
 828//             editor.text(cx),
 829//             "const THREE: usize = 1;\nconst TWO: usize = one::THREE + one::THREE;"
 830//         );
 831//     });
 832
 833//     // Ensure temporary rename edits cannot be undone/redone.
 834//     editor_b.update(cx_b, |editor, cx| {
 835//         editor.undo(&Undo, cx);
 836//         assert_eq!(editor.text(cx), "const ONE: usize = 1;");
 837//         editor.undo(&Undo, cx);
 838//         assert_eq!(editor.text(cx), "const ONE: usize = 1;");
 839//         editor.redo(&Redo, cx);
 840//         assert_eq!(editor.text(cx), "const THREE: usize = 1;");
 841//     })
 842// }
 843
 844// #[gpui::test(iterations = 10)]
 845// async fn test_language_server_statuses(
 846//     executor: BackgroundExecutor,
 847//     cx_a: &mut TestAppContext,
 848//     cx_b: &mut TestAppContext,
 849// ) {
 850//     let mut server = TestServer::start(&executor).await;
 851//     let client_a = server.create_client(cx_a, "user_a").await;
 852//     let client_b = server.create_client(cx_b, "user_b").await;
 853//     server
 854//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
 855//         .await;
 856//     let active_call_a = cx_a.read(ActiveCall::global);
 857
 858//     cx_b.update(editor::init);
 859
 860//     // Set up a fake language server.
 861//     let mut language = Language::new(
 862//         LanguageConfig {
 863//             name: "Rust".into(),
 864//             path_suffixes: vec!["rs".to_string()],
 865//             ..Default::default()
 866//         },
 867//         Some(tree_sitter_rust::language()),
 868//     );
 869//     let mut fake_language_servers = language
 870//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 871//             name: "the-language-server",
 872//             ..Default::default()
 873//         }))
 874//         .await;
 875//     client_a.language_registry().add(Arc::new(language));
 876
 877//     client_a
 878//         .fs()
 879//         .insert_tree(
 880//             "/dir",
 881//             json!({
 882//                 "main.rs": "const ONE: usize = 1;",
 883//             }),
 884//         )
 885//         .await;
 886//     let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
 887
 888//     let _buffer_a = project_a
 889//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
 890//         .await
 891//         .unwrap();
 892
 893//     let fake_language_server = fake_language_servers.next().await.unwrap();
 894//     fake_language_server.start_progress("the-token").await;
 895//     fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams {
 896//         token: lsp::NumberOrString::String("the-token".to_string()),
 897//         value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report(
 898//             lsp::WorkDoneProgressReport {
 899//                 message: Some("the-message".to_string()),
 900//                 ..Default::default()
 901//             },
 902//         )),
 903//     });
 904//     executor.run_until_parked();
 905
 906//     project_a.read_with(cx_a, |project, _| {
 907//         let status = project.language_server_statuses().next().unwrap();
 908//         assert_eq!(status.name, "the-language-server");
 909//         assert_eq!(status.pending_work.len(), 1);
 910//         assert_eq!(
 911//             status.pending_work["the-token"].message.as_ref().unwrap(),
 912//             "the-message"
 913//         );
 914//     });
 915
 916//     let project_id = active_call_a
 917//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
 918//         .await
 919//         .unwrap();
 920//     executor.run_until_parked();
 921//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
 922
 923//     project_b.read_with(cx_b, |project, _| {
 924//         let status = project.language_server_statuses().next().unwrap();
 925//         assert_eq!(status.name, "the-language-server");
 926//     });
 927
 928//     fake_language_server.notify::<lsp::notification::Progress>(lsp::ProgressParams {
 929//         token: lsp::NumberOrString::String("the-token".to_string()),
 930//         value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Report(
 931//             lsp::WorkDoneProgressReport {
 932//                 message: Some("the-message-2".to_string()),
 933//                 ..Default::default()
 934//             },
 935//         )),
 936//     });
 937//     executor.run_until_parked();
 938
 939//     project_a.read_with(cx_a, |project, _| {
 940//         let status = project.language_server_statuses().next().unwrap();
 941//         assert_eq!(status.name, "the-language-server");
 942//         assert_eq!(status.pending_work.len(), 1);
 943//         assert_eq!(
 944//             status.pending_work["the-token"].message.as_ref().unwrap(),
 945//             "the-message-2"
 946//         );
 947//     });
 948
 949//     project_b.read_with(cx_b, |project, _| {
 950//         let status = project.language_server_statuses().next().unwrap();
 951//         assert_eq!(status.name, "the-language-server");
 952//         assert_eq!(status.pending_work.len(), 1);
 953//         assert_eq!(
 954//             status.pending_work["the-token"].message.as_ref().unwrap(),
 955//             "the-message-2"
 956//         );
 957//     });
 958// }
 959
 960// #[gpui::test(iterations = 10)]
 961// async fn test_share_project(
 962//     executor: BackgroundExecutor,
 963//     cx_a: &mut TestAppContext,
 964//     cx_b: &mut TestAppContext,
 965//     cx_c: &mut TestAppContext,
 966// ) {
 967//     let window_b = cx_b.add_empty_window();
 968//     let mut server = TestServer::start(executor).await;
 969//     let client_a = server.create_client(cx_a, "user_a").await;
 970//     let client_b = server.create_client(cx_b, "user_b").await;
 971//     let client_c = server.create_client(cx_c, "user_c").await;
 972//     server
 973//         .make_contacts(&mut [(&client_a, cx_a), (&client_b, cx_b), (&client_c, cx_c)])
 974//         .await;
 975//     let active_call_a = cx_a.read(ActiveCall::global);
 976//     let active_call_b = cx_b.read(ActiveCall::global);
 977//     let active_call_c = cx_c.read(ActiveCall::global);
 978
 979//     client_a
 980//         .fs()
 981//         .insert_tree(
 982//             "/a",
 983//             json!({
 984//                 ".gitignore": "ignored-dir",
 985//                 "a.txt": "a-contents",
 986//                 "b.txt": "b-contents",
 987//                 "ignored-dir": {
 988//                     "c.txt": "",
 989//                     "d.txt": "",
 990//                 }
 991//             }),
 992//         )
 993//         .await;
 994
 995//     // Invite client B to collaborate on a project
 996//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
 997//     active_call_a
 998//         .update(cx_a, |call, cx| {
 999//             call.invite(client_b.user_id().unwrap(), Some(project_a.clone()), cx)
1000//         })
1001//         .await
1002//         .unwrap();
1003
1004//     // Join that project as client B
1005
1006//     let incoming_call_b = active_call_b.read_with(cx_b, |call, _| call.incoming());
1007//     executor.run_until_parked();
1008//     let call = incoming_call_b.borrow().clone().unwrap();
1009//     assert_eq!(call.calling_user.github_login, "user_a");
1010//     let initial_project = call.initial_project.unwrap();
1011//     active_call_b
1012//         .update(cx_b, |call, cx| call.accept_incoming(cx))
1013//         .await
1014//         .unwrap();
1015//     let client_b_peer_id = client_b.peer_id().unwrap();
1016//     let project_b = client_b
1017//         .build_remote_project(initial_project.id, cx_b)
1018//         .await;
1019
1020//     let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id());
1021
1022//     executor.run_until_parked();
1023
1024//     project_a.read_with(cx_a, |project, _| {
1025//         let client_b_collaborator = project.collaborators().get(&client_b_peer_id).unwrap();
1026//         assert_eq!(client_b_collaborator.replica_id, replica_id_b);
1027//     });
1028
1029//     project_b.read_with(cx_b, |project, cx| {
1030//         let worktree = project.worktrees().next().unwrap().read(cx);
1031//         assert_eq!(
1032//             worktree.paths().map(AsRef::as_ref).collect::<Vec<_>>(),
1033//             [
1034//                 Path::new(".gitignore"),
1035//                 Path::new("a.txt"),
1036//                 Path::new("b.txt"),
1037//                 Path::new("ignored-dir"),
1038//             ]
1039//         );
1040//     });
1041
1042//     project_b
1043//         .update(cx_b, |project, cx| {
1044//             let worktree = project.worktrees().next().unwrap();
1045//             let entry = worktree.read(cx).entry_for_path("ignored-dir").unwrap();
1046//             project.expand_entry(worktree_id, entry.id, cx).unwrap()
1047//         })
1048//         .await
1049//         .unwrap();
1050
1051//     project_b.read_with(cx_b, |project, cx| {
1052//         let worktree = project.worktrees().next().unwrap().read(cx);
1053//         assert_eq!(
1054//             worktree.paths().map(AsRef::as_ref).collect::<Vec<_>>(),
1055//             [
1056//                 Path::new(".gitignore"),
1057//                 Path::new("a.txt"),
1058//                 Path::new("b.txt"),
1059//                 Path::new("ignored-dir"),
1060//                 Path::new("ignored-dir/c.txt"),
1061//                 Path::new("ignored-dir/d.txt"),
1062//             ]
1063//         );
1064//     });
1065
1066//     // Open the same file as client B and client A.
1067//     let buffer_b = project_b
1068//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "b.txt"), cx))
1069//         .await
1070//         .unwrap();
1071
1072//     buffer_b.read_with(cx_b, |buf, _| assert_eq!(buf.text(), "b-contents"));
1073
1074//     project_a.read_with(cx_a, |project, cx| {
1075//         assert!(project.has_open_buffer((worktree_id, "b.txt"), cx))
1076//     });
1077//     let buffer_a = project_a
1078//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "b.txt"), cx))
1079//         .await
1080//         .unwrap();
1081
1082//     let editor_b = window_b.build_view(cx_b, |cx| Editor::for_buffer(buffer_b, None, cx));
1083
1084//     // Client A sees client B's selection
1085//     executor.run_until_parked();
1086
1087//     buffer_a.read_with(cx_a, |buffer, _| {
1088//         buffer
1089//             .snapshot()
1090//             .remote_selections_in_range(Anchor::MIN..Anchor::MAX)
1091//             .count()
1092//             == 1
1093//     });
1094
1095//     // Edit the buffer as client B and see that edit as client A.
1096//     editor_b.update(cx_b, |editor, cx| editor.handle_input("ok, ", cx));
1097//     executor.run_until_parked();
1098
1099//     buffer_a.read_with(cx_a, |buffer, _| {
1100//         assert_eq!(buffer.text(), "ok, b-contents")
1101//     });
1102
1103//     // Client B can invite client C on a project shared by client A.
1104//     active_call_b
1105//         .update(cx_b, |call, cx| {
1106//             call.invite(client_c.user_id().unwrap(), Some(project_b.clone()), cx)
1107//         })
1108//         .await
1109//         .unwrap();
1110
1111//     let incoming_call_c = active_call_c.read_with(cx_c, |call, _| call.incoming());
1112//     executor.run_until_parked();
1113//     let call = incoming_call_c.borrow().clone().unwrap();
1114//     assert_eq!(call.calling_user.github_login, "user_b");
1115//     let initial_project = call.initial_project.unwrap();
1116//     active_call_c
1117//         .update(cx_c, |call, cx| call.accept_incoming(cx))
1118//         .await
1119//         .unwrap();
1120//     let _project_c = client_c
1121//         .build_remote_project(initial_project.id, cx_c)
1122//         .await;
1123
1124//     // Client B closes the editor, and client A sees client B's selections removed.
1125//     cx_b.update(move |_| drop(editor_b));
1126//     executor.run_until_parked();
1127
1128//     buffer_a.read_with(cx_a, |buffer, _| {
1129//         buffer
1130//             .snapshot()
1131//             .remote_selections_in_range(Anchor::MIN..Anchor::MAX)
1132//             .count()
1133//             == 0
1134//     });
1135// }
1136
1137// #[gpui::test(iterations = 10)]
1138// async fn test_on_input_format_from_host_to_guest(
1139//     executor: BackgroundExecutor,
1140//     cx_a: &mut TestAppContext,
1141//     cx_b: &mut TestAppContext,
1142// ) {
1143//     let mut server = TestServer::start(&executor).await;
1144//     let client_a = server.create_client(cx_a, "user_a").await;
1145//     let client_b = server.create_client(cx_b, "user_b").await;
1146//     server
1147//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
1148//         .await;
1149//     let active_call_a = cx_a.read(ActiveCall::global);
1150
1151//     // Set up a fake language server.
1152//     let mut language = Language::new(
1153//         LanguageConfig {
1154//             name: "Rust".into(),
1155//             path_suffixes: vec!["rs".to_string()],
1156//             ..Default::default()
1157//         },
1158//         Some(tree_sitter_rust::language()),
1159//     );
1160//     let mut fake_language_servers = language
1161//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
1162//             capabilities: lsp::ServerCapabilities {
1163//                 document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions {
1164//                     first_trigger_character: ":".to_string(),
1165//                     more_trigger_character: Some(vec![">".to_string()]),
1166//                 }),
1167//                 ..Default::default()
1168//             },
1169//             ..Default::default()
1170//         }))
1171//         .await;
1172//     client_a.language_registry().add(Arc::new(language));
1173
1174//     client_a
1175//         .fs()
1176//         .insert_tree(
1177//             "/a",
1178//             json!({
1179//                 "main.rs": "fn main() { a }",
1180//                 "other.rs": "// Test file",
1181//             }),
1182//         )
1183//         .await;
1184//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
1185//     let project_id = active_call_a
1186//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
1187//         .await
1188//         .unwrap();
1189//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
1190
1191//     // Open a file in an editor as the host.
1192//     let buffer_a = project_a
1193//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
1194//         .await
1195//         .unwrap();
1196//     let window_a = cx_a.add_empty_window();
1197//     let editor_a = window_a
1198//         .update(cx_a, |_, cx| {
1199//             cx.build_view(|cx| Editor::for_buffer(buffer_a, Some(project_a.clone()), cx))
1200//         })
1201//         .unwrap();
1202
1203//     let fake_language_server = fake_language_servers.next().await.unwrap();
1204//     executor.run_until_parked();
1205
1206//     // Receive an OnTypeFormatting request as the host's language server.
1207//     // Return some formattings from the host's language server.
1208//     fake_language_server.handle_request::<lsp::request::OnTypeFormatting, _, _>(
1209//         |params, _| async move {
1210//             assert_eq!(
1211//                 params.text_document_position.text_document.uri,
1212//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
1213//             );
1214//             assert_eq!(
1215//                 params.text_document_position.position,
1216//                 lsp::Position::new(0, 14),
1217//             );
1218
1219//             Ok(Some(vec![lsp::TextEdit {
1220//                 new_text: "~<".to_string(),
1221//                 range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
1222//             }]))
1223//         },
1224//     );
1225
1226//     // Open the buffer on the guest and see that the formattings worked
1227//     let buffer_b = project_b
1228//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
1229//         .await
1230//         .unwrap();
1231
1232//     // Type a on type formatting trigger character as the guest.
1233//     editor_a.update(cx_a, |editor, cx| {
1234//         cx.focus(&editor_a);
1235//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
1236//         editor.handle_input(">", cx);
1237//     });
1238
1239//     executor.run_until_parked();
1240
1241//     buffer_b.read_with(cx_b, |buffer, _| {
1242//         assert_eq!(buffer.text(), "fn main() { a>~< }")
1243//     });
1244
1245//     // Undo should remove LSP edits first
1246//     editor_a.update(cx_a, |editor, cx| {
1247//         assert_eq!(editor.text(cx), "fn main() { a>~< }");
1248//         editor.undo(&Undo, cx);
1249//         assert_eq!(editor.text(cx), "fn main() { a> }");
1250//     });
1251//     executor.run_until_parked();
1252
1253//     buffer_b.read_with(cx_b, |buffer, _| {
1254//         assert_eq!(buffer.text(), "fn main() { a> }")
1255//     });
1256
1257//     editor_a.update(cx_a, |editor, cx| {
1258//         assert_eq!(editor.text(cx), "fn main() { a> }");
1259//         editor.undo(&Undo, cx);
1260//         assert_eq!(editor.text(cx), "fn main() { a }");
1261//     });
1262//     executor.run_until_parked();
1263
1264//     buffer_b.read_with(cx_b, |buffer, _| {
1265//         assert_eq!(buffer.text(), "fn main() { a }")
1266//     });
1267// }
1268
1269// #[gpui::test(iterations = 10)]
1270// async fn test_on_input_format_from_guest_to_host(
1271//     executor: BackgroundExecutor,
1272//     cx_a: &mut TestAppContext,
1273//     cx_b: &mut TestAppContext,
1274// ) {
1275//     let mut server = TestServer::start(&executor).await;
1276//     let client_a = server.create_client(cx_a, "user_a").await;
1277//     let client_b = server.create_client(cx_b, "user_b").await;
1278//     server
1279//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
1280//         .await;
1281//     let active_call_a = cx_a.read(ActiveCall::global);
1282
1283//     // Set up a fake language server.
1284//     let mut language = Language::new(
1285//         LanguageConfig {
1286//             name: "Rust".into(),
1287//             path_suffixes: vec!["rs".to_string()],
1288//             ..Default::default()
1289//         },
1290//         Some(tree_sitter_rust::language()),
1291//     );
1292//     let mut fake_language_servers = language
1293//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
1294//             capabilities: lsp::ServerCapabilities {
1295//                 document_on_type_formatting_provider: Some(lsp::DocumentOnTypeFormattingOptions {
1296//                     first_trigger_character: ":".to_string(),
1297//                     more_trigger_character: Some(vec![">".to_string()]),
1298//                 }),
1299//                 ..Default::default()
1300//             },
1301//             ..Default::default()
1302//         }))
1303//         .await;
1304//     client_a.language_registry().add(Arc::new(language));
1305
1306//     client_a
1307//         .fs()
1308//         .insert_tree(
1309//             "/a",
1310//             json!({
1311//                 "main.rs": "fn main() { a }",
1312//                 "other.rs": "// Test file",
1313//             }),
1314//         )
1315//         .await;
1316//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
1317//     let project_id = active_call_a
1318//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
1319//         .await
1320//         .unwrap();
1321//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
1322
1323//     // Open a file in an editor as the guest.
1324//     let buffer_b = project_b
1325//         .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
1326//         .await
1327//         .unwrap();
1328//     let window_b = cx_b.add_empty_window();
1329//     let editor_b = window_b.build_view(cx_b, |cx| {
1330//         Editor::for_buffer(buffer_b, Some(project_b.clone()), cx)
1331//     });
1332
1333//     let fake_language_server = fake_language_servers.next().await.unwrap();
1334//     executor.run_until_parked();
1335//     // Type a on type formatting trigger character as the guest.
1336//     editor_b.update(cx_b, |editor, cx| {
1337//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
1338//         editor.handle_input(":", cx);
1339//         cx.focus(&editor_b);
1340//     });
1341
1342//     // Receive an OnTypeFormatting request as the host's language server.
1343//     // Return some formattings from the host's language server.
1344//     cx_a.foreground().start_waiting();
1345//     fake_language_server
1346//         .handle_request::<lsp::request::OnTypeFormatting, _, _>(|params, _| async move {
1347//             assert_eq!(
1348//                 params.text_document_position.text_document.uri,
1349//                 lsp::Url::from_file_path("/a/main.rs").unwrap(),
1350//             );
1351//             assert_eq!(
1352//                 params.text_document_position.position,
1353//                 lsp::Position::new(0, 14),
1354//             );
1355
1356//             Ok(Some(vec![lsp::TextEdit {
1357//                 new_text: "~:".to_string(),
1358//                 range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
1359//             }]))
1360//         })
1361//         .next()
1362//         .await
1363//         .unwrap();
1364//     cx_a.foreground().finish_waiting();
1365
1366//     // Open the buffer on the host and see that the formattings worked
1367//     let buffer_a = project_a
1368//         .update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
1369//         .await
1370//         .unwrap();
1371//     executor.run_until_parked();
1372
1373//     buffer_a.read_with(cx_a, |buffer, _| {
1374//         assert_eq!(buffer.text(), "fn main() { a:~: }")
1375//     });
1376
1377//     // Undo should remove LSP edits first
1378//     editor_b.update(cx_b, |editor, cx| {
1379//         assert_eq!(editor.text(cx), "fn main() { a:~: }");
1380//         editor.undo(&Undo, cx);
1381//         assert_eq!(editor.text(cx), "fn main() { a: }");
1382//     });
1383//     executor.run_until_parked();
1384
1385//     buffer_a.read_with(cx_a, |buffer, _| {
1386//         assert_eq!(buffer.text(), "fn main() { a: }")
1387//     });
1388
1389//     editor_b.update(cx_b, |editor, cx| {
1390//         assert_eq!(editor.text(cx), "fn main() { a: }");
1391//         editor.undo(&Undo, cx);
1392//         assert_eq!(editor.text(cx), "fn main() { a }");
1393//     });
1394//     executor.run_until_parked();
1395
1396//     buffer_a.read_with(cx_a, |buffer, _| {
1397//         assert_eq!(buffer.text(), "fn main() { a }")
1398//     });
1399// }
1400
1401// #[gpui::test(iterations = 10)]
1402// async fn test_mutual_editor_inlay_hint_cache_update(
1403//     executor: BackgroundExecutor,
1404//     cx_a: &mut TestAppContext,
1405//     cx_b: &mut TestAppContext,
1406// ) {
1407//     let mut server = TestServer::start(&executor).await;
1408//     let client_a = server.create_client(cx_a, "user_a").await;
1409//     let client_b = server.create_client(cx_b, "user_b").await;
1410//     server
1411//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
1412//         .await;
1413//     let active_call_a = cx_a.read(ActiveCall::global);
1414//     let active_call_b = cx_b.read(ActiveCall::global);
1415
1416//     cx_a.update(editor::init);
1417//     cx_b.update(editor::init);
1418
1419//     cx_a.update(|cx| {
1420//         cx.update_global(|store: &mut SettingsStore, cx| {
1421//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
1422//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
1423//                     enabled: true,
1424//                     show_type_hints: true,
1425//                     show_parameter_hints: false,
1426//                     show_other_hints: true,
1427//                 })
1428//             });
1429//         });
1430//     });
1431//     cx_b.update(|cx| {
1432//         cx.update_global(|store: &mut SettingsStore, cx| {
1433//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
1434//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
1435//                     enabled: true,
1436//                     show_type_hints: true,
1437//                     show_parameter_hints: false,
1438//                     show_other_hints: true,
1439//                 })
1440//             });
1441//         });
1442//     });
1443
1444//     let mut language = Language::new(
1445//         LanguageConfig {
1446//             name: "Rust".into(),
1447//             path_suffixes: vec!["rs".to_string()],
1448//             ..Default::default()
1449//         },
1450//         Some(tree_sitter_rust::language()),
1451//     );
1452//     let mut fake_language_servers = language
1453//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
1454//             capabilities: lsp::ServerCapabilities {
1455//                 inlay_hint_provider: Some(lsp::OneOf::Left(true)),
1456//                 ..Default::default()
1457//             },
1458//             ..Default::default()
1459//         }))
1460//         .await;
1461//     let language = Arc::new(language);
1462//     client_a.language_registry().add(Arc::clone(&language));
1463//     client_b.language_registry().add(language);
1464
1465//     // Client A opens a project.
1466//     client_a
1467//         .fs()
1468//         .insert_tree(
1469//             "/a",
1470//             json!({
1471//                 "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out",
1472//                 "other.rs": "// Test file",
1473//             }),
1474//         )
1475//         .await;
1476//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
1477//     active_call_a
1478//         .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx))
1479//         .await
1480//         .unwrap();
1481//     let project_id = active_call_a
1482//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
1483//         .await
1484//         .unwrap();
1485
1486//     // Client B joins the project
1487//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
1488//     active_call_b
1489//         .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
1490//         .await
1491//         .unwrap();
1492
1493//     let workspace_a = client_a.build_workspace(&project_a, cx_a).root_view(cx_a);
1494//     cx_a.foreground().start_waiting();
1495
1496//     // The host opens a rust file.
1497//     let _buffer_a = project_a
1498//         .update(cx_a, |project, cx| {
1499//             project.open_local_buffer("/a/main.rs", cx)
1500//         })
1501//         .await
1502//         .unwrap();
1503//     let fake_language_server = fake_language_servers.next().await.unwrap();
1504//     let editor_a = workspace_a
1505//         .update(cx_a, |workspace, cx| {
1506//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
1507//         })
1508//         .await
1509//         .unwrap()
1510//         .downcast::<Editor>()
1511//         .unwrap();
1512
1513//     // Set up the language server to return an additional inlay hint on each request.
1514//     let edits_made = Arc::new(AtomicUsize::new(0));
1515//     let closure_edits_made = Arc::clone(&edits_made);
1516//     fake_language_server
1517//         .handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
1518//             let task_edits_made = Arc::clone(&closure_edits_made);
1519//             async move {
1520//                 assert_eq!(
1521//                     params.text_document.uri,
1522//                     lsp::Url::from_file_path("/a/main.rs").unwrap(),
1523//                 );
1524//                 let edits_made = task_edits_made.load(atomic::Ordering::Acquire);
1525//                 Ok(Some(vec![lsp::InlayHint {
1526//                     position: lsp::Position::new(0, edits_made as u32),
1527//                     label: lsp::InlayHintLabel::String(edits_made.to_string()),
1528//                     kind: None,
1529//                     text_edits: None,
1530//                     tooltip: None,
1531//                     padding_left: None,
1532//                     padding_right: None,
1533//                     data: None,
1534//                 }]))
1535//             }
1536//         })
1537//         .next()
1538//         .await
1539//         .unwrap();
1540
1541//     executor.run_until_parked();
1542
1543//     let initial_edit = edits_made.load(atomic::Ordering::Acquire);
1544//     editor_a.update(cx_a, |editor, _| {
1545//         assert_eq!(
1546//             vec![initial_edit.to_string()],
1547//             extract_hint_labels(editor),
1548//             "Host should get its first hints when opens an editor"
1549//         );
1550//         let inlay_cache = editor.inlay_hint_cache();
1551//         assert_eq!(
1552//             inlay_cache.version(),
1553//             1,
1554//             "Host editor update the cache version after every cache/view change",
1555//         );
1556//     });
1557//     let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
1558//     let editor_b = workspace_b
1559//         .update(cx_b, |workspace, cx| {
1560//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
1561//         })
1562//         .await
1563//         .unwrap()
1564//         .downcast::<Editor>()
1565//         .unwrap();
1566
1567//     executor.run_until_parked();
1568//     editor_b.update(cx_b, |editor, _| {
1569//         assert_eq!(
1570//             vec![initial_edit.to_string()],
1571//             extract_hint_labels(editor),
1572//             "Client should get its first hints when opens an editor"
1573//         );
1574//         let inlay_cache = editor.inlay_hint_cache();
1575//         assert_eq!(
1576//             inlay_cache.version(),
1577//             1,
1578//             "Guest editor update the cache version after every cache/view change"
1579//         );
1580//     });
1581
1582//     let after_client_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
1583//     editor_b.update(cx_b, |editor, cx| {
1584//         editor.change_selections(None, cx, |s| s.select_ranges([13..13].clone()));
1585//         editor.handle_input(":", cx);
1586//         cx.focus(&editor_b);
1587//     });
1588
1589//     executor.run_until_parked();
1590//     editor_a.update(cx_a, |editor, _| {
1591//         assert_eq!(
1592//             vec![after_client_edit.to_string()],
1593//             extract_hint_labels(editor),
1594//         );
1595//         let inlay_cache = editor.inlay_hint_cache();
1596//         assert_eq!(inlay_cache.version(), 2);
1597//     });
1598//     editor_b.update(cx_b, |editor, _| {
1599//         assert_eq!(
1600//             vec![after_client_edit.to_string()],
1601//             extract_hint_labels(editor),
1602//         );
1603//         let inlay_cache = editor.inlay_hint_cache();
1604//         assert_eq!(inlay_cache.version(), 2);
1605//     });
1606
1607//     let after_host_edit = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
1608//     editor_a.update(cx_a, |editor, cx| {
1609//         editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
1610//         editor.handle_input("a change to increment both buffers' versions", cx);
1611//         cx.focus(&editor_a);
1612//     });
1613
1614//     executor.run_until_parked();
1615//     editor_a.update(cx_a, |editor, _| {
1616//         assert_eq!(
1617//             vec![after_host_edit.to_string()],
1618//             extract_hint_labels(editor),
1619//         );
1620//         let inlay_cache = editor.inlay_hint_cache();
1621//         assert_eq!(inlay_cache.version(), 3);
1622//     });
1623//     editor_b.update(cx_b, |editor, _| {
1624//         assert_eq!(
1625//             vec![after_host_edit.to_string()],
1626//             extract_hint_labels(editor),
1627//         );
1628//         let inlay_cache = editor.inlay_hint_cache();
1629//         assert_eq!(inlay_cache.version(), 3);
1630//     });
1631
1632//     let after_special_edit_for_refresh = edits_made.fetch_add(1, atomic::Ordering::Release) + 1;
1633//     fake_language_server
1634//         .request::<lsp::request::InlayHintRefreshRequest>(())
1635//         .await
1636//         .expect("inlay refresh request failed");
1637
1638//     executor.run_until_parked();
1639//     editor_a.update(cx_a, |editor, _| {
1640//         assert_eq!(
1641//             vec![after_special_edit_for_refresh.to_string()],
1642//             extract_hint_labels(editor),
1643//             "Host should react to /refresh LSP request"
1644//         );
1645//         let inlay_cache = editor.inlay_hint_cache();
1646//         assert_eq!(
1647//             inlay_cache.version(),
1648//             4,
1649//             "Host should accepted all edits and bump its cache version every time"
1650//         );
1651//     });
1652//     editor_b.update(cx_b, |editor, _| {
1653//         assert_eq!(
1654//             vec![after_special_edit_for_refresh.to_string()],
1655//             extract_hint_labels(editor),
1656//             "Guest should get a /refresh LSP request propagated by host"
1657//         );
1658//         let inlay_cache = editor.inlay_hint_cache();
1659//         assert_eq!(
1660//             inlay_cache.version(),
1661//             4,
1662//             "Guest should accepted all edits and bump its cache version every time"
1663//         );
1664//     });
1665// }
1666
1667// #[gpui::test(iterations = 10)]
1668// async fn test_inlay_hint_refresh_is_forwarded(
1669//     executor: BackgroundExecutor,
1670//     cx_a: &mut TestAppContext,
1671//     cx_b: &mut TestAppContext,
1672// ) {
1673//     let mut server = TestServer::start(&executor).await;
1674//     let client_a = server.create_client(cx_a, "user_a").await;
1675//     let client_b = server.create_client(cx_b, "user_b").await;
1676//     server
1677//         .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
1678//         .await;
1679//     let active_call_a = cx_a.read(ActiveCall::global);
1680//     let active_call_b = cx_b.read(ActiveCall::global);
1681
1682//     cx_a.update(editor::init);
1683//     cx_b.update(editor::init);
1684
1685//     cx_a.update(|cx| {
1686//         cx.update_global(|store: &mut SettingsStore, cx| {
1687//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
1688//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
1689//                     enabled: false,
1690//                     show_type_hints: false,
1691//                     show_parameter_hints: false,
1692//                     show_other_hints: false,
1693//                 })
1694//             });
1695//         });
1696//     });
1697//     cx_b.update(|cx| {
1698//         cx.update_global(|store: &mut SettingsStore, cx| {
1699//             store.update_user_settings::<AllLanguageSettings>(cx, |settings| {
1700//                 settings.defaults.inlay_hints = Some(InlayHintSettings {
1701//                     enabled: true,
1702//                     show_type_hints: true,
1703//                     show_parameter_hints: true,
1704//                     show_other_hints: true,
1705//                 })
1706//             });
1707//         });
1708//     });
1709
1710//     let mut language = Language::new(
1711//         LanguageConfig {
1712//             name: "Rust".into(),
1713//             path_suffixes: vec!["rs".to_string()],
1714//             ..Default::default()
1715//         },
1716//         Some(tree_sitter_rust::language()),
1717//     );
1718//     let mut fake_language_servers = language
1719//         .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
1720//             capabilities: lsp::ServerCapabilities {
1721//                 inlay_hint_provider: Some(lsp::OneOf::Left(true)),
1722//                 ..Default::default()
1723//             },
1724//             ..Default::default()
1725//         }))
1726//         .await;
1727//     let language = Arc::new(language);
1728//     client_a.language_registry().add(Arc::clone(&language));
1729//     client_b.language_registry().add(language);
1730
1731//     client_a
1732//         .fs()
1733//         .insert_tree(
1734//             "/a",
1735//             json!({
1736//                 "main.rs": "fn main() { a } // and some long comment to ensure inlay hints are not trimmed out",
1737//                 "other.rs": "// Test file",
1738//             }),
1739//         )
1740//         .await;
1741//     let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
1742//     active_call_a
1743//         .update(cx_a, |call, cx| call.set_location(Some(&project_a), cx))
1744//         .await
1745//         .unwrap();
1746//     let project_id = active_call_a
1747//         .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
1748//         .await
1749//         .unwrap();
1750
1751//     let project_b = client_b.build_remote_project(project_id, cx_b).await;
1752//     active_call_b
1753//         .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
1754//         .await
1755//         .unwrap();
1756
1757//     let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a);
1758//     let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b);
1759//     cx_a.foreground().start_waiting();
1760//     cx_b.foreground().start_waiting();
1761
1762//     let editor_a = workspace_a
1763//         .update(cx_a, |workspace, cx| {
1764//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
1765//         })
1766//         .await
1767//         .unwrap()
1768//         .downcast::<Editor>()
1769//         .unwrap();
1770
1771//     let editor_b = workspace_b
1772//         .update(cx_b, |workspace, cx| {
1773//             workspace.open_path((worktree_id, "main.rs"), None, true, cx)
1774//         })
1775//         .await
1776//         .unwrap()
1777//         .downcast::<Editor>()
1778//         .unwrap();
1779
1780//     let other_hints = Arc::new(AtomicBool::new(false));
1781//     let fake_language_server = fake_language_servers.next().await.unwrap();
1782//     let closure_other_hints = Arc::clone(&other_hints);
1783//     fake_language_server
1784//         .handle_request::<lsp::request::InlayHintRequest, _, _>(move |params, _| {
1785//             let task_other_hints = Arc::clone(&closure_other_hints);
1786//             async move {
1787//                 assert_eq!(
1788//                     params.text_document.uri,
1789//                     lsp::Url::from_file_path("/a/main.rs").unwrap(),
1790//                 );
1791//                 let other_hints = task_other_hints.load(atomic::Ordering::Acquire);
1792//                 let character = if other_hints { 0 } else { 2 };
1793//                 let label = if other_hints {
1794//                     "other hint"
1795//                 } else {
1796//                     "initial hint"
1797//                 };
1798//                 Ok(Some(vec![lsp::InlayHint {
1799//                     position: lsp::Position::new(0, character),
1800//                     label: lsp::InlayHintLabel::String(label.to_string()),
1801//                     kind: None,
1802//                     text_edits: None,
1803//                     tooltip: None,
1804//                     padding_left: None,
1805//                     padding_right: None,
1806//                     data: None,
1807//                 }]))
1808//             }
1809//         })
1810//         .next()
1811//         .await
1812//         .unwrap();
1813//     cx_a.foreground().finish_waiting();
1814//     cx_b.foreground().finish_waiting();
1815
1816//     executor.run_until_parked();
1817//     editor_a.update(cx_a, |editor, _| {
1818//         assert!(
1819//             extract_hint_labels(editor).is_empty(),
1820//             "Host should get no hints due to them turned off"
1821//         );
1822//         let inlay_cache = editor.inlay_hint_cache();
1823//         assert_eq!(
1824//             inlay_cache.version(),
1825//             0,
1826//             "Turned off hints should not generate version updates"
1827//         );
1828//     });
1829
1830//     executor.run_until_parked();
1831//     editor_b.update(cx_b, |editor, _| {
1832//         assert_eq!(
1833//             vec!["initial hint".to_string()],
1834//             extract_hint_labels(editor),
1835//             "Client should get its first hints when opens an editor"
1836//         );
1837//         let inlay_cache = editor.inlay_hint_cache();
1838//         assert_eq!(
1839//             inlay_cache.version(),
1840//             1,
1841//             "Should update cache verison after first hints"
1842//         );
1843//     });
1844
1845//     other_hints.fetch_or(true, atomic::Ordering::Release);
1846//     fake_language_server
1847//         .request::<lsp::request::InlayHintRefreshRequest>(())
1848//         .await
1849//         .expect("inlay refresh request failed");
1850//     executor.run_until_parked();
1851//     editor_a.update(cx_a, |editor, _| {
1852//         assert!(
1853//             extract_hint_labels(editor).is_empty(),
1854//             "Host should get nop hints due to them turned off, even after the /refresh"
1855//         );
1856//         let inlay_cache = editor.inlay_hint_cache();
1857//         assert_eq!(
1858//             inlay_cache.version(),
1859//             0,
1860//             "Turned off hints should not generate version updates, again"
1861//         );
1862//     });
1863
1864//     executor.run_until_parked();
1865//     editor_b.update(cx_b, |editor, _| {
1866//         assert_eq!(
1867//             vec!["other hint".to_string()],
1868//             extract_hint_labels(editor),
1869//             "Guest should get a /refresh LSP request propagated by host despite host hints are off"
1870//         );
1871//         let inlay_cache = editor.inlay_hint_cache();
1872//         assert_eq!(
1873//             inlay_cache.version(),
1874//             2,
1875//             "Guest should accepted all edits and bump its cache version every time"
1876//         );
1877//     });
1878// }
1879
1880// fn extract_hint_labels(editor: &Editor) -> Vec<String> {
1881//     let mut labels = Vec::new();
1882//     for hint in editor.inlay_hint_cache().hints() {
1883//         match hint.label {
1884//             project::InlayHintLabel::String(s) => labels.push(s),
1885//             _ => unreachable!(),
1886//         }
1887//     }
1888//     labels
1889// }