use ssh lsp store (#17655)
Release Notes: - ssh remoting: Added support for booting langauge servers (in limited circumstances) --------- Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
130f19d8f9
commit
36eb1c15ea
45 changed files with 1553 additions and 671 deletions
|
@ -4,14 +4,13 @@ use gpui::{AppContext, AsyncAppContext, Context, Model, ModelContext, Task};
|
|||
use language::LanguageRegistry;
|
||||
use project::{
|
||||
buffer_store::BufferStore, project_settings::SettingsObserver, search::SearchQuery,
|
||||
worktree_store::WorktreeStore, LspStore, ProjectPath, WorktreeId, WorktreeSettings,
|
||||
worktree_store::WorktreeStore, LspStore, ProjectPath, WorktreeId,
|
||||
};
|
||||
use remote::SshSession;
|
||||
use rpc::{
|
||||
proto::{self, AnyProtoClient, SSH_PEER_ID, SSH_PROJECT_ID},
|
||||
TypedEnvelope,
|
||||
};
|
||||
use settings::Settings as _;
|
||||
use smol::stream::StreamExt;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
|
@ -33,15 +32,17 @@ impl HeadlessProject {
|
|||
pub fn init(cx: &mut AppContext) {
|
||||
settings::init(cx);
|
||||
language::init(cx);
|
||||
WorktreeSettings::register(cx);
|
||||
project::Project::init_settings(cx);
|
||||
}
|
||||
|
||||
pub fn new(session: Arc<SshSession>, fs: Arc<dyn Fs>, cx: &mut ModelContext<Self>) -> Self {
|
||||
// TODO: we should load the env correctly (as we do in login_shell_env_loaded when stdout is not a pty). Can we re-use the ProjectEnvironment for that?
|
||||
let languages = Arc::new(LanguageRegistry::new(
|
||||
Task::ready(()),
|
||||
cx.background_executor().clone(),
|
||||
));
|
||||
let mut languages =
|
||||
LanguageRegistry::new(Task::ready(()), cx.background_executor().clone());
|
||||
languages
|
||||
.set_language_server_download_dir(PathBuf::from("/Users/conrad/what-could-go-wrong"));
|
||||
|
||||
let languages = Arc::new(languages);
|
||||
|
||||
let worktree_store = cx.new_model(|_| WorktreeStore::new(true, fs.clone()));
|
||||
let buffer_store = cx.new_model(|cx| {
|
||||
|
@ -57,18 +58,17 @@ impl HeadlessProject {
|
|||
});
|
||||
let environment = project::ProjectEnvironment::new(&worktree_store, None, cx);
|
||||
let lsp_store = cx.new_model(|cx| {
|
||||
LspStore::new(
|
||||
let mut lsp_store = LspStore::new_local(
|
||||
buffer_store.clone(),
|
||||
worktree_store.clone(),
|
||||
Some(environment),
|
||||
environment,
|
||||
languages,
|
||||
None,
|
||||
fs.clone(),
|
||||
Some(session.clone().into()),
|
||||
None,
|
||||
Some(0),
|
||||
cx,
|
||||
)
|
||||
);
|
||||
lsp_store.shared(SSH_PROJECT_ID, session.clone().into(), cx);
|
||||
lsp_store
|
||||
});
|
||||
|
||||
let client: AnyProtoClient = session.clone().into();
|
||||
|
@ -88,9 +88,12 @@ impl HeadlessProject {
|
|||
client.add_model_request_handler(BufferStore::handle_update_buffer);
|
||||
client.add_model_message_handler(BufferStore::handle_close_buffer);
|
||||
|
||||
client.add_model_request_handler(LspStore::handle_create_language_server);
|
||||
|
||||
BufferStore::init(&client);
|
||||
WorktreeStore::init(&client);
|
||||
SettingsObserver::init(&client);
|
||||
LspStore::init(&client);
|
||||
|
||||
HeadlessProject {
|
||||
session: client,
|
||||
|
|
|
@ -6,7 +6,7 @@ use gpui::{Context, Model, TestAppContext};
|
|||
use http_client::FakeHttpClient;
|
||||
use language::{
|
||||
language_settings::{all_language_settings, AllLanguageSettings},
|
||||
Buffer, LanguageRegistry,
|
||||
Buffer, FakeLspAdapter, LanguageConfig, LanguageMatcher, LanguageRegistry,
|
||||
};
|
||||
use node_runtime::FakeNodeRuntime;
|
||||
use project::{
|
||||
|
@ -202,15 +202,29 @@ async fn test_remote_settings(cx: &mut TestAppContext, server_cx: &mut TestAppCo
|
|||
server_cx.read(|cx| {
|
||||
assert_eq!(
|
||||
AllLanguageSettings::get_global(cx)
|
||||
.language(Some("Rust"))
|
||||
.language(Some(&"Rust".into()))
|
||||
.language_servers,
|
||||
["custom-rust-analyzer".into()]
|
||||
)
|
||||
});
|
||||
|
||||
fs.insert_tree("/code/project1/.zed", json!({
|
||||
"settings.json": r#"{"languages":{"Rust":{"language_servers":["override-rust-analyzer"]}}}"#
|
||||
})).await;
|
||||
fs.insert_tree(
|
||||
"/code/project1/.zed",
|
||||
json!({
|
||||
"settings.json": r#"
|
||||
{
|
||||
"languages": {"Rust":{"language_servers":["override-rust-analyzer"]}},
|
||||
"lsp": {
|
||||
"override-rust-analyzer": {
|
||||
"binary": {
|
||||
"path": "~/.cargo/bin/rust-analyzer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}"#
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
let worktree_id = project
|
||||
.update(cx, |project, cx| {
|
||||
|
@ -247,7 +261,7 @@ async fn test_remote_settings(cx: &mut TestAppContext, server_cx: &mut TestAppCo
|
|||
}),
|
||||
cx
|
||||
)
|
||||
.language(Some("Rust"))
|
||||
.language(Some(&"Rust".into()))
|
||||
.language_servers,
|
||||
["override-rust-analyzer".into()]
|
||||
)
|
||||
|
@ -257,13 +271,107 @@ async fn test_remote_settings(cx: &mut TestAppContext, server_cx: &mut TestAppCo
|
|||
let file = buffer.read(cx).file();
|
||||
assert_eq!(
|
||||
all_language_settings(file, cx)
|
||||
.language(Some("Rust"))
|
||||
.language(Some(&"Rust".into()))
|
||||
.language_servers,
|
||||
["override-rust-analyzer".into()]
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_remote_lsp(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
|
||||
let (project, headless, fs) = init_test(cx, server_cx).await;
|
||||
|
||||
fs.insert_tree(
|
||||
"/code/project1/.zed",
|
||||
json!({
|
||||
"settings.json": r#"
|
||||
{
|
||||
"languages": {"Rust":{"language_servers":["rust-analyzer"]}},
|
||||
"lsp": {
|
||||
"rust-analyzer": {
|
||||
"binary": {
|
||||
"path": "~/.cargo/bin/rust-analyzer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}"#
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
cx.update_model(&project, |project, _| {
|
||||
project.languages().register_test_language(LanguageConfig {
|
||||
name: "Rust".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["rs".into()],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
});
|
||||
project.languages().register_fake_lsp_adapter(
|
||||
"Rust",
|
||||
FakeLspAdapter {
|
||||
name: "rust-analyzer",
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
let worktree_id = project
|
||||
.update(cx, |project, cx| {
|
||||
project.find_or_create_worktree("/code/project1", true, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.0
|
||||
.read_with(cx, |worktree, _| worktree.id());
|
||||
|
||||
// Wait for the settings to synchronize
|
||||
cx.run_until_parked();
|
||||
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer((worktree_id, Path::new("src/lib.rs")), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.read(|cx| {
|
||||
let file = buffer.read(cx).file();
|
||||
assert_eq!(
|
||||
all_language_settings(file, cx)
|
||||
.language(Some(&"Rust".into()))
|
||||
.language_servers,
|
||||
["rust-analyzer".into()]
|
||||
)
|
||||
});
|
||||
|
||||
let buffer_id = cx.read(|cx| {
|
||||
let buffer = buffer.read(cx);
|
||||
assert_eq!(buffer.language().unwrap().name(), "Rust".into());
|
||||
buffer.remote_id()
|
||||
});
|
||||
|
||||
server_cx.read(|cx| {
|
||||
let buffer = headless
|
||||
.read(cx)
|
||||
.buffer_store
|
||||
.read(cx)
|
||||
.get(buffer_id)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(buffer.read(cx).language().unwrap().name(), "Rust".into());
|
||||
});
|
||||
|
||||
server_cx.read(|cx| {
|
||||
let lsp_store = headless.read(cx).lsp_store.read(cx);
|
||||
assert_eq!(lsp_store.as_local().unwrap().language_servers.len(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
if std::env::var("RUST_LOG").is_ok() {
|
||||
env_logger::try_init().ok();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue