Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #ISSUE Release Notes: - N/A or Added/Fixed/Improved ...
161 lines
4.9 KiB
Rust
161 lines
4.9 KiB
Rust
use std::path::Path;
|
|
|
|
use fs::FakeFs;
|
|
use futures::StreamExt;
|
|
use gpui::TestAppContext;
|
|
use language::{CodeLabel, FakeLspAdapter, HighlightId, rust_lang};
|
|
use lsp::Uri;
|
|
use project::{Project, lsp_store::*};
|
|
use serde_json::json;
|
|
use util::path;
|
|
|
|
use crate::init_test;
|
|
|
|
#[gpui::test]
|
|
async fn test_removing_invisible_worktree_cleans_reused_lsp_bookkeeping(cx: &mut TestAppContext) {
|
|
init_test(cx);
|
|
cx.executor().allow_parking();
|
|
|
|
let fs = FakeFs::new(cx.executor());
|
|
fs.insert_tree(path!("/the-root"), json!({ "main.rs": "fn main() {}" }))
|
|
.await;
|
|
fs.insert_tree(
|
|
path!("/the-registry"),
|
|
json!({ "dep": { "src": { "dep.rs": "pub fn dep() {}" } } }),
|
|
)
|
|
.await;
|
|
|
|
let project = Project::test(fs, [path!("/the-root").as_ref()], cx).await;
|
|
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
|
language_registry.add(rust_lang());
|
|
let mut fake_servers = language_registry.register_fake_lsp("Rust", FakeLspAdapter::default());
|
|
|
|
let (_visible_buffer, _visible_handle) = project
|
|
.update(cx, |project, cx| {
|
|
project.open_local_buffer_with_lsp(path!("/the-root/main.rs"), cx)
|
|
})
|
|
.await
|
|
.unwrap();
|
|
fake_servers.next().await.unwrap();
|
|
cx.run_until_parked();
|
|
|
|
let server_id = project.read_with(cx, |project, cx| {
|
|
project
|
|
.lsp_store()
|
|
.read(cx)
|
|
.language_server_statuses()
|
|
.next()
|
|
.unwrap()
|
|
.0
|
|
});
|
|
let external_buffer = project
|
|
.update(cx, |project, cx| {
|
|
project.open_local_buffer_via_lsp(
|
|
Uri::from_file_path(path!("/the-registry/dep/src/dep.rs")).unwrap(),
|
|
server_id,
|
|
cx,
|
|
)
|
|
})
|
|
.await
|
|
.unwrap();
|
|
cx.run_until_parked();
|
|
|
|
let invisible_worktree_id =
|
|
external_buffer.read_with(cx, |buffer, cx| buffer.file().unwrap().worktree_id(cx));
|
|
project.read_with(cx, |project, cx| {
|
|
let worktree = project.worktree_for_id(invisible_worktree_id, cx).unwrap();
|
|
assert!(!worktree.read(cx).is_visible());
|
|
assert!(
|
|
project
|
|
.lsp_store()
|
|
.read(cx)
|
|
.has_language_server_seed_for_worktree(invisible_worktree_id)
|
|
);
|
|
});
|
|
|
|
project.update(cx, |project, cx| {
|
|
project.remove_worktree(invisible_worktree_id, cx);
|
|
});
|
|
cx.run_until_parked();
|
|
|
|
project.read_with(cx, |project, cx| {
|
|
let lsp_store = project.lsp_store();
|
|
let lsp_store = lsp_store.read(cx);
|
|
assert!(
|
|
lsp_store
|
|
.language_server_statuses()
|
|
.any(|(status_server_id, _)| status_server_id == server_id)
|
|
);
|
|
assert!(!lsp_store.has_language_server_seed_for_worktree(invisible_worktree_id));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_glob_literal_prefix() {
|
|
assert_eq!(glob_literal_prefix(Path::new("**/*.js")), Path::new(""));
|
|
assert_eq!(
|
|
glob_literal_prefix(Path::new("node_modules/**/*.js")),
|
|
Path::new("node_modules")
|
|
);
|
|
assert_eq!(
|
|
glob_literal_prefix(Path::new("foo/{bar,baz}.js")),
|
|
Path::new("foo")
|
|
);
|
|
assert_eq!(
|
|
glob_literal_prefix(Path::new("foo/bar/baz.js")),
|
|
Path::new("foo/bar/baz.js")
|
|
);
|
|
|
|
#[cfg(target_os = "windows")]
|
|
{
|
|
assert_eq!(glob_literal_prefix(Path::new("**\\*.js")), Path::new(""));
|
|
assert_eq!(
|
|
glob_literal_prefix(Path::new("node_modules\\**/*.js")),
|
|
Path::new("node_modules")
|
|
);
|
|
assert_eq!(
|
|
glob_literal_prefix(Path::new("foo/{bar,baz}.js")),
|
|
Path::new("foo")
|
|
);
|
|
assert_eq!(
|
|
glob_literal_prefix(Path::new("foo\\bar\\baz.js")),
|
|
Path::new("foo/bar/baz.js")
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_multi_len_chars_normalization() {
|
|
let mut label = CodeLabel::new(
|
|
"myElˇ (parameter) myElˇ: {\n foo: string;\n}".to_string(),
|
|
0..6,
|
|
vec![(0..6, HighlightId::new(1))],
|
|
);
|
|
ensure_uniform_list_compatible_label(&mut label);
|
|
assert_eq!(
|
|
label,
|
|
CodeLabel::new(
|
|
"myElˇ (parameter) myElˇ: { foo: string; }".to_string(),
|
|
0..6,
|
|
vec![(0..6, HighlightId::new(1))],
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_trailing_newline_in_completion_documentation() {
|
|
let doc =
|
|
lsp::Documentation::String("Inappropriate argument value (of correct type).\n".to_string());
|
|
let completion_doc: CompletionDocumentation = doc.into();
|
|
assert!(
|
|
matches!(completion_doc, CompletionDocumentation::SingleLine(s) if s == "Inappropriate argument value (of correct type).")
|
|
);
|
|
|
|
let doc = lsp::Documentation::String(" some value \n".to_string());
|
|
let completion_doc: CompletionDocumentation = doc.into();
|
|
assert!(matches!(
|
|
completion_doc,
|
|
CompletionDocumentation::SingleLine(s) if s == "some value"
|
|
));
|
|
}
|