Fix leak when project is unshared while LSP handler waits for edits

This commit is contained in:
Max Brunsfeld 2023-04-10 16:06:28 -07:00
parent e853e77d59
commit 25e3c4e586
6 changed files with 95 additions and 63 deletions

View file

@ -161,9 +161,9 @@ impl LspCommand for PrepareRename {
.ok_or_else(|| anyhow!("invalid position"))?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
Ok(Self {
position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
@ -199,9 +199,9 @@ impl LspCommand for PrepareRename {
if message.can_rename {
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
let start = message.start.and_then(deserialize_anchor);
let end = message.end.and_then(deserialize_anchor);
Ok(start.zip(end).map(|(start, end)| start..end))
@ -281,9 +281,9 @@ impl LspCommand for PerformRename {
.ok_or_else(|| anyhow!("invalid position"))?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
Ok(Self {
position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
new_name: message.new_name,
@ -378,9 +378,9 @@ impl LspCommand for GetDefinition {
.ok_or_else(|| anyhow!("invalid position"))?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
Ok(Self {
position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
})
@ -464,9 +464,9 @@ impl LspCommand for GetTypeDefinition {
.ok_or_else(|| anyhow!("invalid position"))?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
Ok(Self {
position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
})
@ -537,7 +537,7 @@ async fn location_links_from_proto(
.ok_or_else(|| anyhow!("missing origin end"))?;
buffer
.update(&mut cx, |buffer, _| buffer.wait_for_anchors([&start, &end]))
.await;
.await?;
Some(Location {
buffer,
range: start..end,
@ -562,7 +562,7 @@ async fn location_links_from_proto(
.ok_or_else(|| anyhow!("missing target end"))?;
buffer
.update(&mut cx, |buffer, _| buffer.wait_for_anchors([&start, &end]))
.await;
.await?;
let target = Location {
buffer,
range: start..end,
@ -774,9 +774,9 @@ impl LspCommand for GetReferences {
.ok_or_else(|| anyhow!("invalid position"))?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
Ok(Self {
position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
})
@ -827,7 +827,7 @@ impl LspCommand for GetReferences {
.ok_or_else(|| anyhow!("missing target end"))?;
target_buffer
.update(&mut cx, |buffer, _| buffer.wait_for_anchors([&start, &end]))
.await;
.await?;
locations.push(Location {
buffer: target_buffer,
range: start..end,
@ -915,9 +915,9 @@ impl LspCommand for GetDocumentHighlights {
.ok_or_else(|| anyhow!("invalid position"))?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
Ok(Self {
position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
})
@ -965,7 +965,7 @@ impl LspCommand for GetDocumentHighlights {
.ok_or_else(|| anyhow!("missing target end"))?;
buffer
.update(&mut cx, |buffer, _| buffer.wait_for_anchors([&start, &end]))
.await;
.await?;
let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
@ -1117,9 +1117,9 @@ impl LspCommand for GetHover {
.ok_or_else(|| anyhow!("invalid position"))?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(message.version))
buffer.wait_for_version(deserialize_version(&message.version))
})
.await;
.await?;
Ok(Self {
position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
})

View file

@ -1182,6 +1182,11 @@ impl Project {
}
for open_buffer in self.opened_buffers.values_mut() {
// Wake up any tasks waiting for peers' edits to this buffer.
if let Some(buffer) = open_buffer.upgrade(cx) {
buffer.update(cx, |buffer, _| buffer.give_up_waiting());
}
if let OpenBuffer::Strong(buffer) = open_buffer {
*open_buffer = OpenBuffer::Weak(buffer.downgrade());
}
@ -3738,9 +3743,9 @@ impl Project {
} else {
source_buffer_handle
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(response.version))
buffer.wait_for_version(deserialize_version(&response.version))
})
.await;
.await?;
let completions = response.completions.into_iter().map(|completion| {
language::proto::deserialize_completion(completion, language.clone())
@ -3831,7 +3836,7 @@ impl Project {
.update(&mut cx, |buffer, _| {
buffer.wait_for_edits(transaction.edit_ids.iter().copied())
})
.await;
.await?;
if push_to_history {
buffer_handle.update(&mut cx, |buffer, _| {
buffer.push_transaction(transaction.clone(), Instant::now());
@ -3939,9 +3944,9 @@ impl Project {
} else {
buffer_handle
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(response.version))
buffer.wait_for_version(deserialize_version(&response.version))
})
.await;
.await?;
response
.actions
@ -5425,8 +5430,6 @@ impl Project {
mut cx: AsyncAppContext,
) -> Result<proto::BufferSaved> {
let buffer_id = envelope.payload.buffer_id;
let requested_version = deserialize_version(envelope.payload.version);
let (project_id, buffer) = this.update(&mut cx, |this, cx| {
let project_id = this.remote_id().ok_or_else(|| anyhow!("not connected"))?;
let buffer = this
@ -5434,13 +5437,14 @@ impl Project {
.get(&buffer_id)
.and_then(|buffer| buffer.upgrade(cx))
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?;
Ok::<_, anyhow::Error>((project_id, buffer))
anyhow::Ok((project_id, buffer))
})?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(requested_version)
buffer.wait_for_version(deserialize_version(&envelope.payload.version))
})
.await;
.await?;
let buffer_id = buffer.read_with(&cx, |buffer, _| buffer.remote_id());
let (saved_version, fingerprint, mtime) = this
.update(&mut cx, |this, cx| this.save_buffer(buffer, cx))
@ -5503,7 +5507,7 @@ impl Project {
this.shared_buffers.entry(guest_id).or_default().clear();
for buffer in envelope.payload.buffers {
let buffer_id = buffer.id;
let remote_version = language::proto::deserialize_version(buffer.version);
let remote_version = language::proto::deserialize_version(&buffer.version);
if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
this.shared_buffers
.entry(guest_id)
@ -5619,10 +5623,10 @@ impl Project {
.ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))
})?;
let version = deserialize_version(envelope.payload.version);
let version = deserialize_version(&envelope.payload.version);
buffer
.update(&mut cx, |buffer, _| buffer.wait_for_version(version))
.await;
.await?;
let version = buffer.read_with(&cx, |buffer, _| buffer.version());
let position = envelope
@ -5710,9 +5714,9 @@ impl Project {
})?;
buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(envelope.payload.version))
buffer.wait_for_version(deserialize_version(&envelope.payload.version))
})
.await;
.await?;
let version = buffer.read_with(&cx, |buffer, _| buffer.version());
let code_actions = this.update(&mut cx, |this, cx| {
@ -5979,7 +5983,7 @@ impl Project {
.update(&mut cx, |buffer, _| {
buffer.wait_for_edits(transaction.edit_ids.iter().copied())
})
.await;
.await?;
if push_to_history {
buffer.update(&mut cx, |buffer, _| {
@ -6098,7 +6102,7 @@ impl Project {
let send_updates_for_buffers = response.buffers.into_iter().map(|buffer| {
let client = client.clone();
let buffer_id = buffer.id;
let remote_version = language::proto::deserialize_version(buffer.version);
let remote_version = language::proto::deserialize_version(&buffer.version);
this.read_with(&cx, |this, cx| {
if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
let operations = buffer.read(cx).serialize_ops(Some(remote_version), cx);
@ -6263,7 +6267,7 @@ impl Project {
mut cx: AsyncAppContext,
) -> Result<()> {
let fingerprint = deserialize_fingerprint(&envelope.payload.fingerprint)?;
let version = deserialize_version(envelope.payload.version);
let version = deserialize_version(&envelope.payload.version);
let mtime = envelope
.payload
.mtime
@ -6296,7 +6300,7 @@ impl Project {
mut cx: AsyncAppContext,
) -> Result<()> {
let payload = envelope.payload;
let version = deserialize_version(payload.version);
let version = deserialize_version(&payload.version);
let fingerprint = deserialize_fingerprint(&payload.fingerprint)?;
let line_ending = deserialize_line_ending(
proto::LineEnding::from_i32(payload.line_ending)

View file

@ -1064,7 +1064,7 @@ impl RemoteWorktree {
version: serialize_version(&version),
})
.await?;
let version = deserialize_version(response.version);
let version = deserialize_version(&response.version);
let fingerprint = deserialize_fingerprint(&response.fingerprint)?;
let mtime = response
.mtime