lsp: Send DidOpen notifications when changing selections in multi buffer (#22958)
Fixes #22773 Release Notes: - Fixed an edge case with multibuffers that could break language features within them.
This commit is contained in:
parent
f700268029
commit
b6b06cf6d8
5 changed files with 54 additions and 34 deletions
|
@ -18,7 +18,7 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
use unindent::Unindent as _;
|
||||
use util::{post_inc, RandomCharIter};
|
||||
use util::{path, post_inc, RandomCharIter};
|
||||
|
||||
#[ctor::ctor]
|
||||
fn init_logger() {
|
||||
|
@ -33,7 +33,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
|||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
"/test",
|
||||
path!("/test"),
|
||||
json!({
|
||||
"consts.rs": "
|
||||
const a: i32 = 'a';
|
||||
|
@ -59,7 +59,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
|||
.await;
|
||||
|
||||
let language_server_id = LanguageServerId(0);
|
||||
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
|
||||
let project = Project::test(fs.clone(), [path!("/test").as_ref()], cx).await;
|
||||
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
|
||||
let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let cx = &mut VisualTestContext::from_window(*window, cx);
|
||||
|
@ -70,7 +70,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
language_server_id,
|
||||
PathBuf::from("/test/main.rs"),
|
||||
PathBuf::from(path!("/test/main.rs")),
|
||||
None,
|
||||
vec![
|
||||
DiagnosticEntry {
|
||||
|
@ -234,7 +234,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
language_server_id,
|
||||
PathBuf::from("/test/consts.rs"),
|
||||
PathBuf::from(path!("/test/consts.rs")),
|
||||
None,
|
||||
vec![DiagnosticEntry {
|
||||
range: Unclipped(PointUtf16::new(0, 15))..Unclipped(PointUtf16::new(0, 15)),
|
||||
|
@ -341,7 +341,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
language_server_id,
|
||||
PathBuf::from("/test/consts.rs"),
|
||||
PathBuf::from(path!("/test/consts.rs")),
|
||||
None,
|
||||
vec![
|
||||
DiagnosticEntry {
|
||||
|
@ -464,7 +464,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
|||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
"/test",
|
||||
path!("/test"),
|
||||
json!({
|
||||
"main.js": "
|
||||
a();
|
||||
|
@ -479,7 +479,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
|||
|
||||
let server_id_1 = LanguageServerId(100);
|
||||
let server_id_2 = LanguageServerId(101);
|
||||
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
|
||||
let project = Project::test(fs.clone(), [path!("/test").as_ref()], cx).await;
|
||||
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
|
||||
let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let cx = &mut VisualTestContext::from_window(*window, cx);
|
||||
|
@ -504,7 +504,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
server_id_1,
|
||||
PathBuf::from("/test/main.js"),
|
||||
PathBuf::from(path!("/test/main.js")),
|
||||
None,
|
||||
vec![DiagnosticEntry {
|
||||
range: Unclipped(PointUtf16::new(0, 0))..Unclipped(PointUtf16::new(0, 1)),
|
||||
|
@ -557,7 +557,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
server_id_2,
|
||||
PathBuf::from("/test/main.js"),
|
||||
PathBuf::from(path!("/test/main.js")),
|
||||
None,
|
||||
vec![DiagnosticEntry {
|
||||
range: Unclipped(PointUtf16::new(1, 0))..Unclipped(PointUtf16::new(1, 1)),
|
||||
|
@ -619,7 +619,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
server_id_1,
|
||||
PathBuf::from("/test/main.js"),
|
||||
PathBuf::from(path!("/test/main.js")),
|
||||
None,
|
||||
vec![DiagnosticEntry {
|
||||
range: Unclipped(PointUtf16::new(2, 0))..Unclipped(PointUtf16::new(2, 1)),
|
||||
|
@ -638,7 +638,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
server_id_2,
|
||||
PathBuf::from("/test/main.rs"),
|
||||
PathBuf::from(path!("/test/main.rs")),
|
||||
None,
|
||||
vec![],
|
||||
cx,
|
||||
|
@ -689,7 +689,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
|||
lsp_store
|
||||
.update_diagnostic_entries(
|
||||
server_id_2,
|
||||
PathBuf::from("/test/main.js"),
|
||||
PathBuf::from(path!("/test/main.js")),
|
||||
None,
|
||||
vec![DiagnosticEntry {
|
||||
range: Unclipped(PointUtf16::new(3, 0))..Unclipped(PointUtf16::new(3, 1)),
|
||||
|
@ -755,9 +755,9 @@ async fn test_random_diagnostics(cx: &mut TestAppContext, mut rng: StdRng) {
|
|||
.unwrap_or(10);
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree("/test", json!({})).await;
|
||||
fs.insert_tree(path!("/test"), json!({})).await;
|
||||
|
||||
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
|
||||
let project = Project::test(fs.clone(), [path!("/test").as_ref()], cx).await;
|
||||
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
|
||||
let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let cx = &mut VisualTestContext::from_window(*window, cx);
|
||||
|
@ -817,7 +817,7 @@ async fn test_random_diagnostics(cx: &mut TestAppContext, mut rng: StdRng) {
|
|||
// insert a set of diagnostics for a new path
|
||||
_ => {
|
||||
let path: PathBuf =
|
||||
format!("/test/{}.rs", post_inc(&mut next_filename)).into();
|
||||
format!(path!("/test/{}.rs"), post_inc(&mut next_filename)).into();
|
||||
let len = rng.gen_range(128..256);
|
||||
let content =
|
||||
RandomCharIter::new(&mut rng).take(len).collect::<String>();
|
||||
|
@ -891,7 +891,7 @@ async fn test_random_diagnostics(cx: &mut TestAppContext, mut rng: StdRng) {
|
|||
for diagnostic in diagnostics {
|
||||
let found_excerpt = reference_excerpts.iter().any(|info| {
|
||||
let row_range = info.range.context.start.row..info.range.context.end.row;
|
||||
info.path == path.strip_prefix("/test").unwrap()
|
||||
info.path == path.strip_prefix(path!("/test")).unwrap()
|
||||
&& info.language_server == language_server_id
|
||||
&& row_range.contains(&diagnostic.range.start.0.row)
|
||||
});
|
||||
|
|
|
@ -1793,7 +1793,7 @@ impl Editor {
|
|||
self.collapse_matches = collapse_matches;
|
||||
}
|
||||
|
||||
pub fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
|
||||
fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
|
||||
let buffers = self.buffer.read(cx).all_buffers();
|
||||
let Some(lsp_store) = self.lsp_store(cx) else {
|
||||
return;
|
||||
|
@ -2020,6 +2020,21 @@ impl Editor {
|
|||
None
|
||||
}
|
||||
};
|
||||
if let Some(buffer_id) = new_cursor_position.buffer_id {
|
||||
if !self.registered_buffers.contains_key(&buffer_id) {
|
||||
if let Some(lsp_store) = self.lsp_store(cx) {
|
||||
lsp_store.update(cx, |lsp_store, cx| {
|
||||
let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
|
||||
return;
|
||||
};
|
||||
self.registered_buffers.insert(
|
||||
buffer_id,
|
||||
lsp_store.register_buffer_with_language_servers(&buffer, cx),
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(completion_menu) = completion_menu {
|
||||
let cursor_position = new_cursor_position.to_offset(buffer);
|
||||
|
|
|
@ -14875,7 +14875,7 @@ async fn test_multi_buffer_folding(cx: &mut gpui::TestAppContext) {
|
|||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
"/a",
|
||||
path!("/a"),
|
||||
json!({
|
||||
"first.rs": sample_text_1,
|
||||
"second.rs": sample_text_2,
|
||||
|
@ -14883,7 +14883,7 @@ async fn test_multi_buffer_folding(cx: &mut gpui::TestAppContext) {
|
|||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
let project = Project::test(fs, [path!("/a").as_ref()], cx).await;
|
||||
let workspace = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
|
||||
let worktree = project.update(cx, |project, cx| {
|
||||
|
@ -15059,7 +15059,7 @@ async fn test_multi_buffer_single_excerpts_folding(cx: &mut gpui::TestAppContext
|
|||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
"/a",
|
||||
path!("/a"),
|
||||
json!({
|
||||
"first.rs": sample_text_1,
|
||||
"second.rs": sample_text_2,
|
||||
|
@ -15067,7 +15067,7 @@ async fn test_multi_buffer_single_excerpts_folding(cx: &mut gpui::TestAppContext
|
|||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
let project = Project::test(fs, [path!("/a").as_ref()], cx).await;
|
||||
let workspace = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
|
||||
let worktree = project.update(cx, |project, cx| {
|
||||
|
@ -15206,13 +15206,13 @@ async fn test_multi_buffer_with_single_excerpt_folding(cx: &mut gpui::TestAppCon
|
|||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
"/a",
|
||||
path!("/a"),
|
||||
json!({
|
||||
"main.rs": sample_text,
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
let project = Project::test(fs, [path!("/a").as_ref()], cx).await;
|
||||
let workspace = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
|
||||
let worktree = project.update(cx, |project, cx| {
|
||||
|
|
|
@ -1977,7 +1977,12 @@ impl LocalLspStore {
|
|||
Some(local) => local.abs_path(cx),
|
||||
None => return,
|
||||
};
|
||||
let file_url = lsp::Url::from_file_path(old_path).unwrap();
|
||||
let file_url = lsp::Url::from_file_path(old_path.as_path()).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"`{}` is not parseable as an URI",
|
||||
old_path.to_string_lossy()
|
||||
)
|
||||
});
|
||||
self.unregister_buffer_from_language_servers(buffer, file_url, cx);
|
||||
}
|
||||
|
||||
|
|
|
@ -2197,7 +2197,7 @@ pub mod tests {
|
|||
|
||||
let fs = FakeFs::new(cx.background_executor.clone());
|
||||
fs.insert_tree(
|
||||
"/dir",
|
||||
path!("/dir"),
|
||||
json!({
|
||||
"one.rs": "const ONE: usize = 1;",
|
||||
"two.rs": "const TWO: usize = one::ONE + one::ONE;",
|
||||
|
@ -2206,7 +2206,7 @@ pub mod tests {
|
|||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;
|
||||
let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let workspace = window.root(cx).unwrap();
|
||||
let search = cx.new(|cx| ProjectSearch::new(project.clone(), cx));
|
||||
|
@ -2564,7 +2564,7 @@ pub mod tests {
|
|||
|
||||
let fs = FakeFs::new(cx.background_executor.clone());
|
||||
fs.insert_tree(
|
||||
"/dir",
|
||||
path!("/dir"),
|
||||
json!({
|
||||
"one.rs": "const ONE: usize = 1;",
|
||||
"two.rs": "const TWO: usize = one::ONE + one::ONE;",
|
||||
|
@ -2573,7 +2573,7 @@ pub mod tests {
|
|||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;
|
||||
let window = cx.add_window(|window, cx| Workspace::test_new(project, window, cx));
|
||||
let workspace = window;
|
||||
let search_bar = window.build_entity(cx, |_, _| ProjectSearchBar::new());
|
||||
|
@ -2859,7 +2859,7 @@ pub mod tests {
|
|||
|
||||
let fs = FakeFs::new(cx.background_executor.clone());
|
||||
fs.insert_tree(
|
||||
"/dir",
|
||||
path!("/dir"),
|
||||
json!({
|
||||
"a": {
|
||||
"one.rs": "const ONE: usize = 1;",
|
||||
|
@ -2984,7 +2984,7 @@ pub mod tests {
|
|||
|
||||
let fs = FakeFs::new(cx.background_executor.clone());
|
||||
fs.insert_tree(
|
||||
"/dir",
|
||||
path!("/dir"),
|
||||
json!({
|
||||
"one.rs": "const ONE: usize = 1;",
|
||||
"two.rs": "const TWO: usize = one::ONE + one::ONE;",
|
||||
|
@ -2993,7 +2993,7 @@ pub mod tests {
|
|||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;
|
||||
let window = cx.add_window(|window, cx| Workspace::test_new(project, window, cx));
|
||||
let workspace = window.root(cx).unwrap();
|
||||
let search_bar = window.build_entity(cx, |_, _| ProjectSearchBar::new());
|
||||
|
@ -3693,7 +3693,7 @@ pub mod tests {
|
|||
// We need many lines in the search results to be able to scroll the window
|
||||
let fs = FakeFs::new(cx.background_executor.clone());
|
||||
fs.insert_tree(
|
||||
"/dir",
|
||||
path!("/dir"),
|
||||
json!({
|
||||
"1.txt": "\n\n\n\n\n A \n\n\n\n\n",
|
||||
"2.txt": "\n\n\n\n\n A \n\n\n\n\n",
|
||||
|
@ -3718,7 +3718,7 @@ pub mod tests {
|
|||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;
|
||||
let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let workspace = window.root(cx).unwrap();
|
||||
let search = cx.new(|cx| ProjectSearch::new(project, cx));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue