Send DidCloseTextDocument
when dropping buffer
Closes https://github.com/zed-industries/zed/issues/434
This commit is contained in:
parent
17114cc6f7
commit
9ce3b1adf2
1 changed files with 88 additions and 76 deletions
|
@ -126,7 +126,7 @@ pub struct CodeAction<T> {
|
||||||
|
|
||||||
struct LanguageServerState {
|
struct LanguageServerState {
|
||||||
server: Arc<LanguageServer>,
|
server: Arc<LanguageServer>,
|
||||||
latest_snapshot: watch::Sender<Option<LanguageServerSnapshot>>,
|
latest_snapshot: watch::Sender<LanguageServerSnapshot>,
|
||||||
pending_snapshots: BTreeMap<usize, LanguageServerSnapshot>,
|
pending_snapshots: BTreeMap<usize, LanguageServerSnapshot>,
|
||||||
next_version: usize,
|
next_version: usize,
|
||||||
_maintain_server: Task<()>,
|
_maintain_server: Task<()>,
|
||||||
|
@ -666,76 +666,21 @@ impl Buffer {
|
||||||
language_server: Option<Arc<lsp::LanguageServer>>,
|
language_server: Option<Arc<lsp::LanguageServer>>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.language_server = if let Some(server) = language_server {
|
self.language_server = if let Some((server, file)) =
|
||||||
let (latest_snapshot_tx, mut latest_snapshot_rx) =
|
language_server.zip(self.file.as_ref().and_then(|f| f.as_local()))
|
||||||
watch::channel::<Option<LanguageServerSnapshot>>();
|
{
|
||||||
|
let initial_snapshot = LanguageServerSnapshot {
|
||||||
let maintain_changes = cx.background().spawn({
|
buffer_snapshot: self.text.snapshot(),
|
||||||
let server = server.clone();
|
version: 0,
|
||||||
async move {
|
path: file.abs_path(cx).into(),
|
||||||
let mut prev_snapshot: Option<LanguageServerSnapshot> = None;
|
|
||||||
while let Some(snapshot) = latest_snapshot_rx.recv().await {
|
|
||||||
if let Some(snapshot) = snapshot {
|
|
||||||
let uri = lsp::Url::from_file_path(&snapshot.path).unwrap();
|
|
||||||
if let Some(prev_snapshot) = prev_snapshot {
|
|
||||||
let changes = lsp::DidChangeTextDocumentParams {
|
|
||||||
text_document: lsp::VersionedTextDocumentIdentifier::new(
|
|
||||||
uri,
|
|
||||||
snapshot.version as i32,
|
|
||||||
),
|
|
||||||
content_changes: snapshot
|
|
||||||
.buffer_snapshot
|
|
||||||
.edits_since::<(PointUtf16, usize)>(
|
|
||||||
prev_snapshot.buffer_snapshot.version(),
|
|
||||||
)
|
|
||||||
.map(|edit| {
|
|
||||||
let edit_start = edit.new.start.0;
|
|
||||||
let edit_end =
|
|
||||||
edit_start + (edit.old.end.0 - edit.old.start.0);
|
|
||||||
let new_text = snapshot
|
|
||||||
.buffer_snapshot
|
|
||||||
.text_for_range(edit.new.start.1..edit.new.end.1)
|
|
||||||
.collect();
|
|
||||||
lsp::TextDocumentContentChangeEvent {
|
|
||||||
range: Some(lsp::Range::new(
|
|
||||||
edit_start.to_lsp_position(),
|
|
||||||
edit_end.to_lsp_position(),
|
|
||||||
)),
|
|
||||||
range_length: None,
|
|
||||||
text: new_text,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
};
|
};
|
||||||
server
|
let (latest_snapshot_tx, mut latest_snapshot_rx) =
|
||||||
.notify::<lsp::notification::DidChangeTextDocument>(changes)
|
watch::channel_with::<LanguageServerSnapshot>(initial_snapshot.clone());
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
server
|
|
||||||
.notify::<lsp::notification::DidOpenTextDocument>(
|
|
||||||
lsp::DidOpenTextDocumentParams {
|
|
||||||
text_document: lsp::TextDocumentItem::new(
|
|
||||||
uri,
|
|
||||||
Default::default(),
|
|
||||||
snapshot.version as i32,
|
|
||||||
snapshot.buffer_snapshot.text().to_string(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_snapshot = Some(snapshot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Some(LanguageServerState {
|
Some(LanguageServerState {
|
||||||
latest_snapshot: latest_snapshot_tx,
|
latest_snapshot: latest_snapshot_tx,
|
||||||
pending_snapshots: Default::default(),
|
pending_snapshots: BTreeMap::from_iter([(0, initial_snapshot)]),
|
||||||
next_version: 0,
|
next_version: 1,
|
||||||
server: server.clone(),
|
server: server.clone(),
|
||||||
_maintain_server: cx.spawn_weak(|this, mut cx| async move {
|
_maintain_server: cx.spawn_weak(|this, mut cx| async move {
|
||||||
let mut capabilities = server.capabilities();
|
let mut capabilities = server.capabilities();
|
||||||
|
@ -762,6 +707,63 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let maintain_changes = cx.background().spawn(async move {
|
||||||
|
let initial_snapshot =
|
||||||
|
latest_snapshot_rx.recv().await.ok_or_else(|| {
|
||||||
|
anyhow!("buffer dropped before sending DidOpenTextDocument")
|
||||||
|
})?;
|
||||||
|
server
|
||||||
|
.notify::<lsp::notification::DidOpenTextDocument>(
|
||||||
|
lsp::DidOpenTextDocumentParams {
|
||||||
|
text_document: lsp::TextDocumentItem::new(
|
||||||
|
lsp::Url::from_file_path(initial_snapshot.path).unwrap(),
|
||||||
|
Default::default(),
|
||||||
|
initial_snapshot.version as i32,
|
||||||
|
initial_snapshot.buffer_snapshot.text(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut prev_version = initial_snapshot.buffer_snapshot.version().clone();
|
||||||
|
while let Some(snapshot) = latest_snapshot_rx.recv().await {
|
||||||
|
let uri = lsp::Url::from_file_path(&snapshot.path).unwrap();
|
||||||
|
let buffer_snapshot = snapshot.buffer_snapshot.clone();
|
||||||
|
let content_changes = buffer_snapshot
|
||||||
|
.edits_since::<(PointUtf16, usize)>(&prev_version)
|
||||||
|
.map(|edit| {
|
||||||
|
let edit_start = edit.new.start.0;
|
||||||
|
let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
|
||||||
|
let new_text = buffer_snapshot
|
||||||
|
.text_for_range(edit.new.start.1..edit.new.end.1)
|
||||||
|
.collect();
|
||||||
|
lsp::TextDocumentContentChangeEvent {
|
||||||
|
range: Some(lsp::Range::new(
|
||||||
|
edit_start.to_lsp_position(),
|
||||||
|
edit_end.to_lsp_position(),
|
||||||
|
)),
|
||||||
|
range_length: None,
|
||||||
|
text: new_text,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let changes = lsp::DidChangeTextDocumentParams {
|
||||||
|
text_document: lsp::VersionedTextDocumentIdentifier::new(
|
||||||
|
uri,
|
||||||
|
snapshot.version as i32,
|
||||||
|
),
|
||||||
|
content_changes,
|
||||||
|
};
|
||||||
|
server
|
||||||
|
.notify::<lsp::notification::DidChangeTextDocument>(changes)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
prev_version = snapshot.buffer_snapshot.version().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok::<_, anyhow::Error>(())
|
||||||
|
});
|
||||||
|
|
||||||
maintain_changes.log_err().await;
|
maintain_changes.log_err().await;
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -1385,24 +1387,22 @@ impl Buffer {
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let abs_path = self
|
let file = if let Some(file) = self.file.as_ref().and_then(|f| f.as_local()) {
|
||||||
.file
|
file
|
||||||
.as_ref()
|
} else {
|
||||||
.and_then(|f| f.as_local())
|
return;
|
||||||
.map_or(Path::new("/").to_path_buf(), |file| file.abs_path(cx));
|
};
|
||||||
|
|
||||||
let version = post_inc(&mut language_server.next_version);
|
let version = post_inc(&mut language_server.next_version);
|
||||||
let snapshot = LanguageServerSnapshot {
|
let snapshot = LanguageServerSnapshot {
|
||||||
buffer_snapshot: self.text.snapshot(),
|
buffer_snapshot: self.text.snapshot(),
|
||||||
version,
|
version,
|
||||||
path: Arc::from(abs_path),
|
path: Arc::from(file.abs_path(cx)),
|
||||||
};
|
};
|
||||||
language_server
|
language_server
|
||||||
.pending_snapshots
|
.pending_snapshots
|
||||||
.insert(version, snapshot.clone());
|
.insert(version, snapshot.clone());
|
||||||
let _ = language_server
|
let _ = language_server.latest_snapshot.blocking_send(snapshot);
|
||||||
.latest_snapshot
|
|
||||||
.blocking_send(Some(snapshot));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit<I, S, T>(
|
pub fn edit<I, S, T>(
|
||||||
|
@ -2049,6 +2049,18 @@ impl Entity for Buffer {
|
||||||
fn release(&mut self, cx: &mut gpui::MutableAppContext) {
|
fn release(&mut self, cx: &mut gpui::MutableAppContext) {
|
||||||
if let Some(file) = self.file.as_ref() {
|
if let Some(file) = self.file.as_ref() {
|
||||||
file.buffer_removed(self.remote_id(), cx);
|
file.buffer_removed(self.remote_id(), cx);
|
||||||
|
if let Some((lang_server, file)) = self.language_server.as_ref().zip(file.as_local()) {
|
||||||
|
let request = lang_server
|
||||||
|
.server
|
||||||
|
.notify::<lsp::notification::DidCloseTextDocument>(
|
||||||
|
lsp::DidCloseTextDocumentParams {
|
||||||
|
text_document: lsp::TextDocumentIdentifier::new(
|
||||||
|
lsp::Url::from_file_path(file.abs_path(cx)).unwrap(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
cx.foreground().spawn(request).detach_and_log_err(cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue