Fix renames over language server for SSH remoting (#17897)
Release Notes: - ssh remoting: Fix rename over language server --------- Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Max <max@zed.dev>
This commit is contained in:
parent
01bb10f518
commit
e66ea9e5d4
34 changed files with 505 additions and 329 deletions
|
@ -46,7 +46,9 @@ gpui = { workspace = true, features = ["test-support"] }
|
|||
http_client = { workspace = true, features = ["test-support"] }
|
||||
language = { workspace = true, features = ["test-support"] }
|
||||
node_runtime = { workspace = true, features = ["test-support"] }
|
||||
project = { workspace = true, features = ["test-support"] }
|
||||
remote = { workspace = true, features = ["test-support"] }
|
||||
lsp = { workspace = true, features=["test-support"] }
|
||||
|
||||
serde_json.workspace = true
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use fs::Fs;
|
||||
use gpui::{AppContext, AsyncAppContext, Context, Model, ModelContext};
|
||||
use language::LanguageRegistry;
|
||||
use language::{proto::serialize_operation, Buffer, BufferEvent, LanguageRegistry};
|
||||
use project::{
|
||||
buffer_store::BufferStore, project_settings::SettingsObserver, search::SearchQuery,
|
||||
worktree_store::WorktreeStore, LspStore, ProjectPath, WorktreeId,
|
||||
buffer_store::{BufferStore, BufferStoreEvent},
|
||||
project_settings::SettingsObserver,
|
||||
search::SearchQuery,
|
||||
worktree_store::WorktreeStore,
|
||||
LspStore, ProjectPath, WorktreeId,
|
||||
};
|
||||
use remote::SshSession;
|
||||
use rpc::{
|
||||
|
@ -26,6 +29,7 @@ pub struct HeadlessProject {
|
|||
pub lsp_store: Model<LspStore>,
|
||||
pub settings_observer: Model<SettingsObserver>,
|
||||
pub next_entry_id: Arc<AtomicUsize>,
|
||||
pub languages: Arc<LanguageRegistry>,
|
||||
}
|
||||
|
||||
impl HeadlessProject {
|
||||
|
@ -60,7 +64,7 @@ impl HeadlessProject {
|
|||
buffer_store.clone(),
|
||||
worktree_store.clone(),
|
||||
environment,
|
||||
languages,
|
||||
languages.clone(),
|
||||
None,
|
||||
fs.clone(),
|
||||
cx,
|
||||
|
@ -69,6 +73,17 @@ impl HeadlessProject {
|
|||
lsp_store
|
||||
});
|
||||
|
||||
cx.subscribe(
|
||||
&buffer_store,
|
||||
|_this, _buffer_store, event, cx| match event {
|
||||
BufferStoreEvent::BufferAdded(buffer) => {
|
||||
cx.subscribe(buffer, Self::on_buffer_event).detach();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
||||
let client: AnyProtoClient = session.clone().into();
|
||||
|
||||
session.subscribe_to_entity(SSH_PROJECT_ID, &worktree_store);
|
||||
|
@ -103,6 +118,26 @@ impl HeadlessProject {
|
|||
buffer_store,
|
||||
lsp_store,
|
||||
next_entry_id: Default::default(),
|
||||
languages,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_buffer_event(
|
||||
&mut self,
|
||||
buffer: Model<Buffer>,
|
||||
event: &BufferEvent,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
BufferEvent::Operation(op) => cx
|
||||
.background_executor()
|
||||
.spawn(self.session.request(proto::UpdateBuffer {
|
||||
project_id: SSH_PROJECT_ID,
|
||||
buffer_id: buffer.read(cx).remote_id().to_proto(),
|
||||
operations: vec![serialize_operation(op)],
|
||||
}))
|
||||
.detach(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@ use gpui::{Context, Model, TestAppContext};
|
|||
use http_client::FakeHttpClient;
|
||||
use language::{
|
||||
language_settings::{all_language_settings, AllLanguageSettings},
|
||||
Buffer, FakeLspAdapter, LanguageConfig, LanguageMatcher, LanguageRegistry,
|
||||
Buffer, FakeLspAdapter, LanguageConfig, LanguageMatcher, LanguageRegistry, LanguageServerName,
|
||||
};
|
||||
use lsp::{CompletionContext, CompletionResponse, CompletionTriggerKind};
|
||||
use node_runtime::FakeNodeRuntime;
|
||||
use project::{
|
||||
search::{SearchQuery, SearchResult},
|
||||
|
@ -317,6 +318,15 @@ async fn test_remote_lsp(cx: &mut TestAppContext, server_cx: &mut TestAppContext
|
|||
},
|
||||
)
|
||||
});
|
||||
|
||||
let mut fake_lsp = server_cx.update(|cx| {
|
||||
headless.read(cx).languages.register_fake_language_server(
|
||||
LanguageServerName("rust-analyzer".into()),
|
||||
Default::default(),
|
||||
None,
|
||||
)
|
||||
});
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
let worktree_id = project
|
||||
|
@ -339,6 +349,8 @@ async fn test_remote_lsp(cx: &mut TestAppContext, server_cx: &mut TestAppContext
|
|||
.unwrap();
|
||||
cx.run_until_parked();
|
||||
|
||||
let fake_lsp = fake_lsp.next().await.unwrap();
|
||||
|
||||
cx.read(|cx| {
|
||||
let file = buffer.read(cx).file();
|
||||
assert_eq!(
|
||||
|
@ -370,6 +382,62 @@ async fn test_remote_lsp(cx: &mut TestAppContext, server_cx: &mut TestAppContext
|
|||
let lsp_store = headless.read(cx).lsp_store.read(cx);
|
||||
assert_eq!(lsp_store.as_local().unwrap().language_servers.len(), 1);
|
||||
});
|
||||
|
||||
fake_lsp.handle_request::<lsp::request::Completion, _, _>(|_, _| async move {
|
||||
Ok(Some(CompletionResponse::Array(vec![lsp::CompletionItem {
|
||||
label: "boop".to_string(),
|
||||
..Default::default()
|
||||
}])))
|
||||
});
|
||||
|
||||
let result = project
|
||||
.update(cx, |project, cx| {
|
||||
project.completions(
|
||||
&buffer,
|
||||
0,
|
||||
CompletionContext {
|
||||
trigger_kind: CompletionTriggerKind::INVOKED,
|
||||
trigger_character: None,
|
||||
},
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.into_iter().map(|c| c.label.text).collect::<Vec<_>>(),
|
||||
vec!["boop".to_string()]
|
||||
);
|
||||
|
||||
fake_lsp.handle_request::<lsp::request::Rename, _, _>(|_, _| async move {
|
||||
Ok(Some(lsp::WorkspaceEdit {
|
||||
changes: Some(
|
||||
[(
|
||||
lsp::Url::from_file_path("/code/project1/src/lib.rs").unwrap(),
|
||||
vec![lsp::TextEdit::new(
|
||||
lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(0, 6)),
|
||||
"two".to_string(),
|
||||
)],
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
..Default::default()
|
||||
}))
|
||||
});
|
||||
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
project.perform_rename(buffer.clone(), 3, "two".to_string(), true, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
buffer.update(cx, |buffer, _| {
|
||||
assert_eq!(buffer.text(), "fn two() -> usize { 1 }")
|
||||
})
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue