Restructure fake language server setup

Replace FakeLanguageServerConfig with FakeLanguageServerAdapter
This commit is contained in:
Max Brunsfeld 2022-03-29 17:54:29 -07:00
parent 158d987965
commit ebc711f9f5
4 changed files with 503 additions and 502 deletions

View File

@ -6438,13 +6438,12 @@ pub fn styled_runs_for_code_label<'a>(
#[cfg(test)]
mod tests {
use super::*;
use gpui::{
geometry::rect::RectF,
platform::{WindowBounds, WindowOptions},
};
use language::{LanguageConfig, LanguageServerConfig};
use language::{FakeLspAdapter, LanguageConfig};
use lsp::FakeLanguageServer;
use project::FakeFs;
use smol::stream::StreamExt;
@ -8880,26 +8879,27 @@ mod tests {
cx.foreground().forbid_parking();
cx.update(populate_settings);
let (mut language_server_config, mut fake_servers) = LanguageServerConfig::fake();
language_server_config.set_fake_capabilities(lsp::ServerCapabilities {
document_formatting_provider: Some(lsp::OneOf::Left(true)),
..Default::default()
});
let language = Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
));
);
let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
capabilities: lsp::ServerCapabilities {
document_formatting_provider: Some(lsp::OneOf::Left(true)),
..Default::default()
},
..Default::default()
});
let fs = FakeFs::new(cx.background().clone());
fs.insert_file("/file.rs", Default::default()).await;
let project = Project::test(fs, cx);
project.update(cx, |project, _| project.languages().add(language));
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
let worktree_id = project
.update(cx, |project, cx| {
@ -8913,6 +8913,8 @@ mod tests {
.update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
.await
.unwrap();
cx.foreground().start_waiting();
let mut fake_server = fake_servers.next().await.unwrap();
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
@ -8934,6 +8936,7 @@ mod tests {
})
.next()
.await;
cx.foreground().start_waiting();
save.await.unwrap();
assert_eq!(
editor.read_with(cx, |editor, cx| editor.text(cx)),
@ -8955,6 +8958,7 @@ mod tests {
});
let save = cx.update(|cx| editor.save(project.clone(), cx));
cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
cx.foreground().start_waiting();
save.await.unwrap();
assert_eq!(
editor.read_with(cx, |editor, cx| editor.text(cx)),
@ -8967,23 +8971,24 @@ mod tests {
async fn test_completion(cx: &mut gpui::TestAppContext) {
cx.update(populate_settings);
let (mut language_server_config, mut fake_servers) = LanguageServerConfig::fake();
language_server_config.set_fake_capabilities(lsp::ServerCapabilities {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
Some(tree_sitter_rust::language()),
);
let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
capabilities: lsp::ServerCapabilities {
completion_provider: Some(lsp::CompletionOptions {
trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
..Default::default()
}),
..Default::default()
});
let language = Arc::new(Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
));
..Default::default()
});
let text = "
one
@ -8996,7 +9001,7 @@ mod tests {
fs.insert_file("/file.rs", text).await;
let project = Project::test(fs, cx);
project.update(cx, |project, _| project.languages().add(language));
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
let worktree_id = project
.update(cx, |project, cx| {

View File

@ -138,16 +138,13 @@ impl Default for LanguageConfig {
pub struct LanguageServerConfig {
pub disk_based_diagnostic_sources: HashSet<String>,
pub disk_based_diagnostics_progress_token: Option<String>,
#[cfg(any(test, feature = "test-support"))]
#[serde(skip)]
fake_config: Option<FakeLanguageServerConfig>,
}
#[cfg(any(test, feature = "test-support"))]
struct FakeLanguageServerConfig {
servers_tx: mpsc::UnboundedSender<lsp::FakeLanguageServer>,
capabilities: lsp::ServerCapabilities,
initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
pub struct FakeLspAdapter {
pub name: &'static str,
pub capabilities: lsp::ServerCapabilities,
pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
}
#[derive(Clone, Debug, Deserialize)]
@ -162,6 +159,12 @@ pub struct Language {
pub(crate) config: LanguageConfig,
pub(crate) grammar: Option<Arc<Grammar>>,
pub(crate) adapter: Option<Arc<dyn LspAdapter>>,
#[cfg(any(test, feature = "test-support"))]
fake_adapter: Option<(
mpsc::UnboundedSender<lsp::FakeLanguageServer>,
Arc<FakeLspAdapter>,
)>,
}
pub struct Grammar {
@ -262,26 +265,22 @@ impl LanguageRegistry {
cx: &mut MutableAppContext,
) -> Option<Task<Result<lsp::LanguageServer>>> {
#[cfg(any(test, feature = "test-support"))]
if language.config.language_server.fake_config.is_some() {
if language.fake_adapter.is_some() {
let language = language.clone();
return Some(cx.spawn(|mut cx| async move {
let fake_config = language
.config
.language_server
.fake_config
.as_ref()
.unwrap();
let (servers_tx, fake_adapter) = language.fake_adapter.as_ref().unwrap();
let (server, mut fake_server) = cx.update(|cx| {
lsp::LanguageServer::fake_with_capabilities(
fake_config.capabilities.clone(),
fake_adapter.capabilities.clone(),
cx,
)
});
if let Some(initializer) = &fake_config.initializer {
if let Some(initializer) = &fake_adapter.initializer {
initializer(&mut fake_server);
}
let servers_tx = fake_config.servers_tx.clone();
let servers_tx = servers_tx.clone();
cx.background()
.spawn(async move {
fake_server
@ -426,6 +425,9 @@ impl Language {
})
}),
adapter: None,
#[cfg(any(test, feature = "test-support"))]
fake_adapter: None,
}
}
@ -478,6 +480,18 @@ impl Language {
self
}
#[cfg(any(test, feature = "test-support"))]
pub fn set_fake_lsp_adapter(
&mut self,
fake_lsp_adapter: FakeLspAdapter,
) -> mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
let (servers_tx, servers_rx) = mpsc::unbounded();
let adapter = Arc::new(fake_lsp_adapter);
self.fake_adapter = Some((servers_tx, adapter.clone()));
self.adapter = Some(adapter);
servers_rx
}
pub fn name(&self) -> Arc<str> {
self.config.name.clone()
}
@ -601,33 +615,42 @@ impl CodeLabel {
}
#[cfg(any(test, feature = "test-support"))]
impl LanguageServerConfig {
pub fn fake() -> (Self, mpsc::UnboundedReceiver<lsp::FakeLanguageServer>) {
let (servers_tx, servers_rx) = mpsc::unbounded();
(
impl Default for FakeLspAdapter {
fn default() -> Self {
Self {
fake_config: Some(FakeLanguageServerConfig {
servers_tx,
name: "the-fake-language-server",
capabilities: lsp::LanguageServer::full_capabilities(),
initializer: None,
}),
disk_based_diagnostics_progress_token: Some("fakeServer/check".to_string()),
..Default::default()
},
servers_rx,
)
}
}
}
impl LspAdapter for FakeLspAdapter {
fn name(&self) -> LanguageServerName {
LanguageServerName(self.name.into())
}
pub fn set_fake_capabilities(&mut self, capabilities: lsp::ServerCapabilities) {
self.fake_config.as_mut().unwrap().capabilities = capabilities;
fn fetch_latest_server_version(
&self,
_: Arc<dyn HttpClient>,
) -> BoxFuture<'static, Result<Box<dyn 'static + Send + Any>>> {
unreachable!();
}
pub fn set_fake_initializer(
&mut self,
initializer: impl 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer),
) {
self.fake_config.as_mut().unwrap().initializer = Some(Box::new(initializer));
fn fetch_server_binary(
&self,
_: Box<dyn 'static + Send + Any>,
_: Arc<dyn HttpClient>,
_: PathBuf,
) -> BoxFuture<'static, Result<PathBuf>> {
unreachable!();
}
fn cached_server_binary(&self, _: PathBuf) -> BoxFuture<'static, Option<PathBuf>> {
unreachable!();
}
fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
}
impl ToLspPosition for PointUtf16 {

View File

@ -4606,8 +4606,8 @@ mod tests {
use futures::StreamExt;
use gpui::test::subscribe;
use language::{
tree_sitter_rust, Diagnostic, LanguageConfig, LanguageServerConfig, OffsetRangeExt, Point,
ToPoint,
tree_sitter_rust, Diagnostic, FakeLspAdapter, LanguageConfig, LanguageServerConfig,
OffsetRangeExt, Point, ToPoint,
};
use lsp::Url;
use serde_json::json;
@ -4683,42 +4683,45 @@ mod tests {
async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
cx.foreground().forbid_parking();
let (mut rust_lsp_config, mut fake_rust_servers) = LanguageServerConfig::fake();
let (mut json_lsp_config, mut fake_json_servers) = LanguageServerConfig::fake();
rust_lsp_config.set_fake_capabilities(lsp::ServerCapabilities {
let mut rust_language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
Some(tree_sitter_rust::language()),
);
let mut json_language = Language::new(
LanguageConfig {
name: "JSON".into(),
path_suffixes: vec!["json".to_string()],
..Default::default()
},
None,
);
let mut fake_rust_servers = rust_language.set_fake_lsp_adapter(FakeLspAdapter {
name: "the-rust-language-server",
capabilities: lsp::ServerCapabilities {
completion_provider: Some(lsp::CompletionOptions {
trigger_characters: Some(vec![".".to_string(), "::".to_string()]),
..Default::default()
}),
..Default::default()
},
..Default::default()
});
json_lsp_config.set_fake_capabilities(lsp::ServerCapabilities {
let mut fake_json_servers = json_language.set_fake_lsp_adapter(FakeLspAdapter {
name: "the-json-language-server",
capabilities: lsp::ServerCapabilities {
completion_provider: Some(lsp::CompletionOptions {
trigger_characters: Some(vec![":".to_string()]),
..Default::default()
}),
..Default::default()
},
..Default::default()
});
let rust_language = Arc::new(Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: rust_lsp_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
));
let json_language = Arc::new(Language::new(
LanguageConfig {
name: "JSON".into(),
path_suffixes: vec!["json".to_string()],
language_server: json_lsp_config,
..Default::default()
},
None,
));
let fs = FakeFs::new(cx.background());
fs.insert_tree(
"/the-root",
@ -4733,8 +4736,8 @@ mod tests {
let project = Project::test(fs, cx);
project.update(cx, |project, _| {
project.languages.add(rust_language);
project.languages.add(json_language);
project.languages.add(Arc::new(rust_language));
project.languages.add(Arc::new(json_language));
});
let worktree_id = project
@ -4903,21 +4906,20 @@ mod tests {
async fn test_disk_based_diagnostics_progress(cx: &mut gpui::TestAppContext) {
cx.foreground().forbid_parking();
let (language_server_config, mut fake_servers) = LanguageServerConfig::fake();
let progress_token = language_server_config
.disk_based_diagnostics_progress_token
.clone()
.unwrap();
let language = Arc::new(Language::new(
let progress_token = "the-progress-token".to_string();
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
language_server: LanguageServerConfig {
disk_based_diagnostics_progress_token: Some(progress_token.clone()),
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
));
);
let mut fake_servers = language.set_fake_lsp_adapter(Default::default());
let fs = FakeFs::new(cx.background());
fs.insert_tree(
@ -4930,7 +4932,7 @@ mod tests {
.await;
let project = Project::test(fs, cx);
project.update(cx, |project, _| project.languages.add(language));
project.update(cx, |project, _| project.languages.add(Arc::new(language)));
let (tree, _) = project
.update(cx, |project, cx| {
@ -5022,19 +5024,20 @@ mod tests {
async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) {
cx.foreground().forbid_parking();
let (mut lsp_config, mut fake_servers) = LanguageServerConfig::fake();
lsp_config
.disk_based_diagnostic_sources
.insert("disk".to_string());
let language = Arc::new(Language::new(
// let (mut lsp_config, mut fake_servers) = LanguageServerConfig::fake();
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: lsp_config,
language_server: LanguageServerConfig {
disk_based_diagnostic_sources: ["disk".to_string()].into_iter().collect(),
..Default::default()
},
..Default::default()
},
Some(tree_sitter_rust::language()),
));
);
let mut fake_servers = language.set_fake_lsp_adapter(Default::default());
let text = "
fn a() { A }
@ -5047,7 +5050,7 @@ mod tests {
fs.insert_tree("/dir", json!({ "a.rs": text })).await;
let project = Project::test(fs, cx);
project.update(cx, |project, _| project.languages.add(language));
project.update(cx, |project, _| project.languages.add(Arc::new(language)));
let worktree_id = project
.update(cx, |project, cx| {
@ -5396,16 +5399,15 @@ mod tests {
async fn test_edits_from_lsp_with_past_version(cx: &mut gpui::TestAppContext) {
cx.foreground().forbid_parking();
let (lsp_config, mut fake_servers) = LanguageServerConfig::fake();
let language = Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: lsp_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
));
);
let mut fake_servers = language.set_fake_lsp_adapter(Default::default());
let text = "
fn a() {
@ -5430,7 +5432,7 @@ mod tests {
.await;
let project = Project::test(fs, cx);
project.update(cx, |project, _| project.languages.add(language));
project.update(cx, |project, _| project.languages.add(Arc::new(language)));
let worktree_id = project
.update(cx, |project, cx| {
@ -5746,16 +5748,15 @@ mod tests {
#[gpui::test]
async fn test_definition(cx: &mut gpui::TestAppContext) {
let (language_server_config, mut fake_servers) = LanguageServerConfig::fake();
let language = Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
));
);
let mut fake_servers = language.set_fake_lsp_adapter(Default::default());
let fs = FakeFs::new(cx.background());
fs.insert_tree(
@ -5768,9 +5769,7 @@ mod tests {
.await;
let project = Project::test(fs, cx);
project.update(cx, |project, _| {
Arc::get_mut(&mut project.languages).unwrap().add(language);
});
project.update(cx, |project, _| project.languages.add(Arc::new(language)));
let (tree, _) = project
.update(cx, |project, cx| {
@ -6682,16 +6681,15 @@ mod tests {
async fn test_rename(cx: &mut gpui::TestAppContext) {
cx.foreground().forbid_parking();
let (language_server_config, mut fake_servers) = LanguageServerConfig::fake();
let language = Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
));
);
let mut fake_servers = language.set_fake_lsp_adapter(Default::default());
let fs = FakeFs::new(cx.background());
fs.insert_tree(
@ -6704,9 +6702,7 @@ mod tests {
.await;
let project = Project::test(fs.clone(), cx);
project.update(cx, |project, _| {
Arc::get_mut(&mut project.languages).unwrap().add(language);
});
project.update(cx, |project, _| project.languages.add(Arc::new(language)));
let (tree, _) = project
.update(cx, |project, cx| {

View File

@ -1088,10 +1088,10 @@ mod tests {
};
use gpui::{executor, geometry::vector::vec2f, ModelHandle, TestAppContext, ViewHandle};
use language::{
tree_sitter_rust, Diagnostic, DiagnosticEntry, Language, LanguageConfig, LanguageRegistry,
LanguageServerConfig, OffsetRangeExt, Point, ToLspPosition,
tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig,
LanguageRegistry, OffsetRangeExt, Point, ToLspPosition,
};
use lsp;
use lsp::{self, FakeLanguageServer};
use parking_lot::Mutex;
use postage::barrier;
use project::{
@ -2039,22 +2039,20 @@ mod tests {
cx_b: &mut TestAppContext,
) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -2261,29 +2259,29 @@ mod tests {
cx_b: &mut TestAppContext,
) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
// Set up a fake language server.
let (mut language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
language_server_config.set_fake_capabilities(lsp::ServerCapabilities {
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
Some(tree_sitter_rust::language()),
);
let mut fake_language_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
capabilities: lsp::ServerCapabilities {
completion_provider: Some(lsp::CompletionOptions {
trigger_characters: Some(vec![".".to_string()]),
..Default::default()
}),
..Default::default()
});
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
..Default::default()
});
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -2463,22 +2461,20 @@ mod tests {
#[gpui::test(iterations = 10)]
async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -2563,7 +2559,7 @@ mod tests {
#[gpui::test(iterations = 10)]
async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
fs.insert_tree(
"/root-1",
@ -2582,18 +2578,16 @@ mod tests {
.await;
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -2705,7 +2699,7 @@ mod tests {
#[gpui::test(iterations = 10)]
async fn test_references(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
fs.insert_tree(
"/root-1",
@ -2725,18 +2719,16 @@ mod tests {
.await;
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -2967,16 +2959,16 @@ mod tests {
.await;
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
lang_registry.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -3092,7 +3084,7 @@ mod tests {
#[gpui::test(iterations = 10)]
async fn test_project_symbols(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
fs.insert_tree(
"/code",
@ -3112,18 +3104,16 @@ mod tests {
.await;
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -3231,7 +3221,7 @@ mod tests {
mut rng: StdRng,
) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
fs.insert_tree(
"/root",
@ -3244,19 +3234,16 @@ mod tests {
.await;
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -3337,23 +3324,21 @@ mod tests {
cx_b: &mut TestAppContext,
) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
cx_b.update(|cx| editor::init(cx));
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -3573,23 +3558,21 @@ mod tests {
#[gpui::test(iterations = 10)]
async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
cx_a.foreground().forbid_parking();
let mut lang_registry = Arc::new(LanguageRegistry::test());
let lang_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx_a.background());
cx_b.update(|cx| editor::init(cx));
// Set up a fake language server.
let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake();
Arc::get_mut(&mut lang_registry)
.unwrap()
.add(Arc::new(Language::new(
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
Some(tree_sitter_rust::language()),
)));
);
let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default());
lang_registry.add(Arc::new(language));
// Connect to a server as 2 clients.
let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await;
@ -4838,7 +4821,7 @@ mod tests {
let rng = Arc::new(Mutex::new(rng));
let guest_lang_registry = Arc::new(LanguageRegistry::test());
let (language_server_config, _fake_language_servers) = LanguageServerConfig::fake();
let host_language_registry = Arc::new(LanguageRegistry::test());
let fs = FakeFs::new(cx.background());
fs.insert_tree(
@ -4852,6 +4835,7 @@ mod tests {
let operations = Rc::new(Cell::new(0));
let mut server = TestServer::start(cx.foreground(), cx.background()).await;
let mut clients = Vec::new();
let files = Arc::new(Mutex::new(Vec::new()));
let mut next_entity_id = 100000;
let mut host_cx = TestAppContext::new(
@ -4868,7 +4852,7 @@ mod tests {
Project::local(
host.client.clone(),
host.user_store.clone(),
Arc::new(LanguageRegistry::test()),
host_language_registry.clone(),
fs.clone(),
cx,
)
@ -4891,9 +4875,138 @@ mod tests {
.await
.unwrap();
// Set up fake language servers.
let mut language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
None,
);
let _fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
name: "the-fake-language-server",
capabilities: lsp::LanguageServer::full_capabilities(),
initializer: Some(Box::new({
let rng = rng.clone();
let files = files.clone();
let project = host_project.downgrade();
move |fake_server: &mut FakeLanguageServer| {
fake_server.handle_request::<lsp::request::Completion, _, _>(
|_, _| async move {
Some(lsp::CompletionResponse::Array(vec![lsp::CompletionItem {
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range::new(
lsp::Position::new(0, 0),
lsp::Position::new(0, 0),
),
new_text: "the-new-text".to_string(),
})),
..Default::default()
}]))
},
);
fake_server.handle_request::<lsp::request::CodeActionRequest, _, _>(
|_, _| async move {
Some(vec![lsp::CodeActionOrCommand::CodeAction(
lsp::CodeAction {
title: "the-code-action".to_string(),
..Default::default()
},
)])
},
);
fake_server.handle_request::<lsp::request::PrepareRenameRequest, _, _>(
|params, _| async move {
Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
params.position,
params.position,
)))
},
);
fake_server.handle_request::<lsp::request::GotoDefinition, _, _>({
let files = files.clone();
let rng = rng.clone();
move |_, _| {
let files = files.clone();
let rng = rng.clone();
async move {
let files = files.lock();
let mut rng = rng.lock();
let count = rng.gen_range::<usize, _>(1..3);
let files = (0..count)
.map(|_| files.choose(&mut *rng).unwrap())
.collect::<Vec<_>>();
log::info!("LSP: Returning definitions in files {:?}", &files);
Some(lsp::GotoDefinitionResponse::Array(
files
.into_iter()
.map(|file| lsp::Location {
uri: lsp::Url::from_file_path(file).unwrap(),
range: Default::default(),
})
.collect(),
))
}
}
});
fake_server.handle_request::<lsp::request::DocumentHighlightRequest, _, _>({
let rng = rng.clone();
let project = project.clone();
move |params, mut cx| {
let highlights = if let Some(project) = project.upgrade(&cx) {
project.update(&mut cx, |project, cx| {
let path = params
.text_document_position_params
.text_document
.uri
.to_file_path()
.unwrap();
let (worktree, relative_path) =
project.find_local_worktree(&path, cx)?;
let project_path =
ProjectPath::from((worktree.read(cx).id(), relative_path));
let buffer =
project.get_open_buffer(&project_path, cx)?.read(cx);
let mut highlights = Vec::new();
let highlight_count = rng.lock().gen_range(1..=5);
let mut prev_end = 0;
for _ in 0..highlight_count {
let range =
buffer.random_byte_range(prev_end, &mut *rng.lock());
let start = buffer
.offset_to_point_utf16(range.start)
.to_lsp_position();
let end = buffer
.offset_to_point_utf16(range.end)
.to_lsp_position();
highlights.push(lsp::DocumentHighlight {
range: lsp::Range::new(start, end),
kind: Some(lsp::DocumentHighlightKind::READ),
});
prev_end = range.end;
}
Some(highlights)
})
} else {
None
};
async move { highlights }
}
});
}
})),
});
host_language_registry.add(Arc::new(language));
clients.push(cx.foreground().spawn(host.simulate_host(
host_project,
language_server_config,
files,
operations.clone(),
max_operations,
rng.clone(),
@ -5324,146 +5437,15 @@ mod tests {
})
}
fn simulate_host(
async fn simulate_host(
mut self,
project: ModelHandle<Project>,
mut language_server_config: LanguageServerConfig,
files: Arc<Mutex<Vec<PathBuf>>>,
operations: Rc<Cell<usize>>,
max_operations: usize,
rng: Arc<Mutex<StdRng>>,
mut cx: TestAppContext,
) -> impl Future<Output = (Self, TestAppContext)> {
let files: Arc<Mutex<Vec<PathBuf>>> = Default::default();
// Set up a fake language server.
language_server_config.set_fake_initializer({
let rng = rng.clone();
let files = files.clone();
let project = project.downgrade();
move |fake_server| {
fake_server.handle_request::<lsp::request::Completion, _, _>(
|_, _| async move {
Some(lsp::CompletionResponse::Array(vec![lsp::CompletionItem {
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: lsp::Range::new(
lsp::Position::new(0, 0),
lsp::Position::new(0, 0),
),
new_text: "the-new-text".to_string(),
})),
..Default::default()
}]))
},
);
fake_server.handle_request::<lsp::request::CodeActionRequest, _, _>(
|_, _| async move {
Some(vec![lsp::CodeActionOrCommand::CodeAction(
lsp::CodeAction {
title: "the-code-action".to_string(),
..Default::default()
},
)])
},
);
fake_server.handle_request::<lsp::request::PrepareRenameRequest, _, _>(
|params, _| async move {
Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
params.position,
params.position,
)))
},
);
fake_server.handle_request::<lsp::request::GotoDefinition, _, _>({
let files = files.clone();
let rng = rng.clone();
move |_, _| {
let files = files.clone();
let rng = rng.clone();
async move {
let files = files.lock();
let mut rng = rng.lock();
let count = rng.gen_range::<usize, _>(1..3);
let files = (0..count)
.map(|_| files.choose(&mut *rng).unwrap())
.collect::<Vec<_>>();
log::info!("LSP: Returning definitions in files {:?}", &files);
Some(lsp::GotoDefinitionResponse::Array(
files
.into_iter()
.map(|file| lsp::Location {
uri: lsp::Url::from_file_path(file).unwrap(),
range: Default::default(),
})
.collect(),
))
}
}
});
fake_server.handle_request::<lsp::request::DocumentHighlightRequest, _, _>({
let rng = rng.clone();
let project = project.clone();
move |params, mut cx| {
let highlights = if let Some(project) = project.upgrade(&cx) {
project.update(&mut cx, |project, cx| {
let path = params
.text_document_position_params
.text_document
.uri
.to_file_path()
.unwrap();
let (worktree, relative_path) =
project.find_local_worktree(&path, cx)?;
let project_path =
ProjectPath::from((worktree.read(cx).id(), relative_path));
let buffer =
project.get_open_buffer(&project_path, cx)?.read(cx);
let mut highlights = Vec::new();
let highlight_count = rng.lock().gen_range(1..=5);
let mut prev_end = 0;
for _ in 0..highlight_count {
let range =
buffer.random_byte_range(prev_end, &mut *rng.lock());
let start = buffer
.offset_to_point_utf16(range.start)
.to_lsp_position();
let end = buffer
.offset_to_point_utf16(range.end)
.to_lsp_position();
highlights.push(lsp::DocumentHighlight {
range: lsp::Range::new(start, end),
kind: Some(lsp::DocumentHighlightKind::READ),
});
prev_end = range.end;
}
Some(highlights)
})
} else {
None
};
async move { highlights }
}
});
}
});
project.update(&mut cx, |project, _| {
project.languages().add(Arc::new(Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
language_server: language_server_config,
..Default::default()
},
None,
)));
});
async move {
) -> (Self, TestAppContext) {
let fs = project.read_with(&cx, |project, _| project.fs().clone());
while operations.get() < max_operations {
operations.set(operations.get() + 1);
@ -5498,11 +5480,7 @@ mod tests {
let file = files.lock().choose(&mut *rng.lock()).unwrap().clone();
let (worktree, path) = project
.update(&mut cx, |project, cx| {
project.find_or_create_local_worktree(
file.clone(),
true,
cx,
)
project.find_or_create_local_worktree(file.clone(), true, cx)
})
.await
.unwrap();
@ -5582,7 +5560,6 @@ mod tests {
self.project = Some(project);
(self, cx)
}
}
pub async fn simulate_guest(
mut self,