Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Max Brunsfeld
8f4f0277f2 Start work on avoiding starting language servers for multi-buffer excerpts
Co-authored-by: Antonio <antonio@zed.dev>
2024-02-01 14:14:04 -08:00
2 changed files with 127 additions and 70 deletions

View file

@ -185,7 +185,12 @@ enum LocalProjectUpdate {
}, },
} }
enum OpenBuffer { struct OpenBuffer {
handle: BufferHandle,
can_start_language_servers: bool,
}
enum BufferHandle {
Strong(Model<Buffer>), Strong(Model<Buffer>),
Weak(WeakModel<Buffer>), Weak(WeakModel<Buffer>),
Operations(Vec<Operation>), Operations(Vec<Operation>),
@ -846,7 +851,7 @@ impl Project {
let mut language_servers_to_start = Vec::new(); let mut language_servers_to_start = Vec::new();
let mut language_formatters_to_check = Vec::new(); let mut language_formatters_to_check = Vec::new();
for buffer in self.opened_buffers.values() { for buffer in self.opened_buffers.values() {
if let Some(buffer) = buffer.upgrade() { if let Some(buffer) = buffer.handle.upgrade() {
let buffer = buffer.read(cx); let buffer = buffer.read(cx);
let buffer_file = File::from_dyn(buffer.file()); let buffer_file = File::from_dyn(buffer.file());
let buffer_language = buffer.language(); let buffer_language = buffer.language();
@ -943,7 +948,7 @@ impl Project {
if self.copilot_lsp_subscription.is_none() { if self.copilot_lsp_subscription.is_none() {
if let Some(copilot) = Copilot::global(cx) { if let Some(copilot) = Copilot::global(cx) {
for buffer in self.opened_buffers.values() { for buffer in self.opened_buffers.values() {
if let Some(buffer) = buffer.upgrade() { if let Some(buffer) = buffer.handle.upgrade() {
self.register_buffer_with_copilot(&buffer, cx); self.register_buffer_with_copilot(&buffer, cx);
} }
} }
@ -957,7 +962,7 @@ impl Project {
pub fn buffer_for_id(&self, remote_id: BufferId) -> Option<Model<Buffer>> { pub fn buffer_for_id(&self, remote_id: BufferId) -> Option<Model<Buffer>> {
self.opened_buffers self.opened_buffers
.get(&remote_id) .get(&remote_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
} }
pub fn languages(&self) -> &Arc<LanguageRegistry> { pub fn languages(&self) -> &Arc<LanguageRegistry> {
@ -975,7 +980,7 @@ impl Project {
pub fn opened_buffers(&self) -> Vec<Model<Buffer>> { pub fn opened_buffers(&self) -> Vec<Model<Buffer>> {
self.opened_buffers self.opened_buffers
.values() .values()
.filter_map(|b| b.upgrade()) .filter_map(|b| b.handle.upgrade())
.collect() .collect()
} }
@ -984,7 +989,7 @@ impl Project {
let path = path.into(); let path = path.into();
if let Some(worktree) = self.worktree_for_id(path.worktree_id, cx) { if let Some(worktree) = self.worktree_for_id(path.worktree_id, cx) {
self.opened_buffers.iter().any(|(_, buffer)| { self.opened_buffers.iter().any(|(_, buffer)| {
if let Some(buffer) = buffer.upgrade() { if let Some(buffer) = buffer.handle.upgrade() {
if let Some(file) = File::from_dyn(buffer.read(cx).file()) { if let Some(file) = File::from_dyn(buffer.read(cx).file()) {
if file.worktree == worktree && file.path() == &path.path { if file.worktree == worktree && file.path() == &path.path {
return true; return true;
@ -1318,14 +1323,14 @@ impl Project {
); );
for open_buffer in self.opened_buffers.values_mut() { for open_buffer in self.opened_buffers.values_mut() {
match open_buffer { match &open_buffer.handle {
OpenBuffer::Strong(_) => {} BufferHandle::Strong(_) => {}
OpenBuffer::Weak(buffer) => { BufferHandle::Weak(buffer) => {
if let Some(buffer) = buffer.upgrade() { if let Some(buffer) = buffer.upgrade() {
*open_buffer = OpenBuffer::Strong(buffer); open_buffer.handle = BufferHandle::Strong(buffer);
} }
} }
OpenBuffer::Operations(_) => unreachable!(), BufferHandle::Operations(_) => unreachable!(),
} }
} }
@ -1398,11 +1403,11 @@ impl Project {
} }
LocalProjectUpdate::CreateBufferForPeer { peer_id, buffer_id } => { LocalProjectUpdate::CreateBufferForPeer { peer_id, buffer_id } => {
let buffer = this.update(&mut cx, |this, _| { let buffer = this.update(&mut cx, |this, _| {
let buffer = this.opened_buffers.get(&buffer_id).unwrap(); let buffer = &this.opened_buffers.get(&buffer_id).unwrap().handle;
let shared_buffers = let shared_buffers =
this.shared_buffers.entry(peer_id).or_default(); this.shared_buffers.entry(peer_id).or_default();
if shared_buffers.insert(buffer_id) { if shared_buffers.insert(buffer_id) {
if let OpenBuffer::Strong(buffer) = buffer { if let BufferHandle::Strong(buffer) = buffer {
Some(buffer.clone()) Some(buffer.clone())
} else { } else {
None None
@ -1544,12 +1549,12 @@ impl Project {
for open_buffer in self.opened_buffers.values_mut() { for open_buffer in self.opened_buffers.values_mut() {
// Wake up any tasks waiting for peers' edits to this buffer. // Wake up any tasks waiting for peers' edits to this buffer.
if let Some(buffer) = open_buffer.upgrade() { if let Some(buffer) = open_buffer.handle.upgrade() {
buffer.update(cx, |buffer, _| buffer.give_up_waiting()); buffer.update(cx, |buffer, _| buffer.give_up_waiting());
} }
if let OpenBuffer::Strong(buffer) = open_buffer { if let BufferHandle::Strong(buffer) = &open_buffer.handle {
*open_buffer = OpenBuffer::Weak(buffer.downgrade()); open_buffer.handle = BufferHandle::Weak(buffer.downgrade());
} }
} }
@ -1610,12 +1615,12 @@ impl Project {
for open_buffer in self.opened_buffers.values_mut() { for open_buffer in self.opened_buffers.values_mut() {
// Wake up any tasks waiting for peers' edits to this buffer. // Wake up any tasks waiting for peers' edits to this buffer.
if let Some(buffer) = open_buffer.upgrade() { if let Some(buffer) = open_buffer.handle.upgrade() {
buffer.update(cx, |buffer, _| buffer.give_up_waiting()); buffer.update(cx, |buffer, _| buffer.give_up_waiting());
} }
if let OpenBuffer::Strong(buffer) = open_buffer { if let BufferHandle::Strong(buffer) = &open_buffer.handle {
*open_buffer = OpenBuffer::Weak(buffer.downgrade()); open_buffer.handle = BufferHandle::Weak(buffer.downgrade());
} }
} }
@ -1949,7 +1954,7 @@ impl Project {
) -> Option<Model<Buffer>> { ) -> Option<Model<Buffer>> {
let worktree = self.worktree_for_id(path.worktree_id, cx)?; let worktree = self.worktree_for_id(path.worktree_id, cx)?;
self.opened_buffers.values().find_map(|buffer| { self.opened_buffers.values().find_map(|buffer| {
let buffer = buffer.upgrade()?; let buffer = buffer.handle.upgrade()?;
let file = File::from_dyn(buffer.read(cx).file())?; let file = File::from_dyn(buffer.read(cx).file())?;
if file.worktree == worktree && file.path() == &path.path { if file.worktree == worktree && file.path() == &path.path {
Some(buffer) Some(buffer)
@ -1971,10 +1976,14 @@ impl Project {
let remote_id = buffer.read(cx).remote_id(); let remote_id = buffer.read(cx).remote_id();
let is_remote = self.is_remote(); let is_remote = self.is_remote();
let open_buffer = if is_remote || self.is_shared() { let handle = if is_remote || self.is_shared() {
OpenBuffer::Strong(buffer.clone()) BufferHandle::Strong(buffer.clone())
} else { } else {
OpenBuffer::Weak(buffer.downgrade()) BufferHandle::Weak(buffer.downgrade())
};
let open_buffer = OpenBuffer {
handle,
can_start_language_servers: false,
}; };
match self.opened_buffers.entry(remote_id) { match self.opened_buffers.entry(remote_id) {
@ -1982,9 +1991,9 @@ impl Project {
entry.insert(open_buffer); entry.insert(open_buffer);
} }
hash_map::Entry::Occupied(mut entry) => { hash_map::Entry::Occupied(mut entry) => {
if let OpenBuffer::Operations(operations) = entry.get_mut() { if let BufferHandle::Operations(operations) = &mut entry.get_mut().handle {
buffer.update(cx, |b, cx| b.apply_ops(operations.drain(..), cx))?; buffer.update(cx, |b, cx| b.apply_ops(operations.drain(..), cx))?;
} else if entry.get().upgrade().is_some() { } else if entry.get().handle.upgrade().is_some() {
if is_remote { if is_remote {
return Ok(()); return Ok(());
} else { } else {
@ -2602,7 +2611,7 @@ impl Project {
let buffers = this let buffers = this
.opened_buffers .opened_buffers
.values() .values()
.filter_map(|b| b.upgrade()) .filter_map(|b| b.handle.upgrade())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for buffer in buffers { for buffer in buffers {
if let Some(f) = File::from_dyn(buffer.read(cx).file()).cloned() if let Some(f) = File::from_dyn(buffer.read(cx).file()).cloned()
@ -2623,7 +2632,7 @@ impl Project {
let mut plain_text_buffers = Vec::new(); let mut plain_text_buffers = Vec::new();
let mut buffers_with_unknown_injections = Vec::new(); let mut buffers_with_unknown_injections = Vec::new();
for buffer in project.opened_buffers.values() { for buffer in project.opened_buffers.values() {
if let Some(handle) = buffer.upgrade() { if let Some(handle) = buffer.handle.upgrade() {
let buffer = &handle.read(cx); let buffer = &handle.read(cx);
if buffer.language().is_none() if buffer.language().is_none()
|| buffer.language() == Some(&*language::PLAIN_TEXT) || buffer.language() == Some(&*language::PLAIN_TEXT)
@ -2720,20 +2729,32 @@ impl Project {
buffer.set_language(Some(new_language.clone()), cx); buffer.set_language(Some(new_language.clone()), cx);
} }
}); });
}
pub fn allow_buffer_to_start_language_servers(
&mut self,
buffer: &Model<Buffer>,
cx: &mut ModelContext<Self>,
) {
let buffer_file = buffer.read(cx).file().cloned(); let buffer_file = buffer.read(cx).file().cloned();
let settings = language_settings(Some(&new_language), buffer_file.as_ref(), cx).clone(); let Some(language) = buffer.read(cx).language().cloned() else {
return;
};
let settings = language_settings(Some(&language), buffer_file.as_ref(), cx).clone();
let buffer_file = File::from_dyn(buffer_file.as_ref()); let buffer_file = File::from_dyn(buffer_file.as_ref());
let worktree = buffer_file.as_ref().map(|f| f.worktree_id(cx)); let worktree = buffer_file.as_ref().map(|f| f.worktree_id(cx));
if let Some(prettier_plugins) = if let Some(prettier_plugins) =
prettier_support::prettier_plugins_for_language(&new_language, &settings) prettier_support::prettier_plugins_for_language(&language, &settings)
{ {
self.install_default_prettier(worktree, prettier_plugins, cx); self.install_default_prettier(worktree, prettier_plugins, cx);
}; };
if let Some(file) = buffer_file { if let Some(file) = buffer_file {
let worktree = file.worktree.clone(); let worktree = file.worktree.clone();
if worktree.read(cx).is_local() { if worktree.read(cx).is_local() {
self.start_language_servers(&worktree, new_language, cx); self.start_language_servers(&worktree, language, cx);
} }
} }
} }
@ -3202,7 +3223,7 @@ impl Project {
// Tell the language server about every open buffer in the worktree that matches the language. // Tell the language server about every open buffer in the worktree that matches the language.
for buffer in self.opened_buffers.values() { for buffer in self.opened_buffers.values() {
if let Some(buffer_handle) = buffer.upgrade() { if let Some(buffer_handle) = buffer.handle.upgrade() {
let buffer = buffer_handle.read(cx); let buffer = buffer_handle.read(cx);
let file = match File::from_dyn(buffer.file()) { let file = match File::from_dyn(buffer.file()) {
Some(file) => file, Some(file) => file,
@ -3296,7 +3317,7 @@ impl Project {
} }
for buffer in self.opened_buffers.values() { for buffer in self.opened_buffers.values() {
if let Some(buffer) = buffer.upgrade() { if let Some(buffer) = buffer.handle.upgrade() {
buffer.update(cx, |buffer, cx| { buffer.update(cx, |buffer, cx| {
buffer.update_diagnostics(server_id, Default::default(), cx); buffer.update_diagnostics(server_id, Default::default(), cx);
}); });
@ -5717,7 +5738,7 @@ impl Project {
.opened_buffers .opened_buffers
.iter() .iter()
.filter_map(|(_, b)| { .filter_map(|(_, b)| {
let buffer = b.upgrade()?; let buffer = b.handle.upgrade()?;
let (is_ignored, snapshot) = buffer.update(cx, |buffer, cx| { let (is_ignored, snapshot) = buffer.update(cx, |buffer, cx| {
let is_ignored = buffer let is_ignored = buffer
.project_path(cx) .project_path(cx)
@ -6447,14 +6468,15 @@ impl Project {
}; };
let open_buffer = self.opened_buffers.get(&buffer_id); let open_buffer = self.opened_buffers.get(&buffer_id);
let buffer = if let Some(buffer) = open_buffer.and_then(|buffer| buffer.upgrade()) { let buffer =
buffer if let Some(buffer) = open_buffer.and_then(|buffer| buffer.handle.upgrade()) {
} else { buffer
self.opened_buffers.remove(&buffer_id); } else {
self.local_buffer_ids_by_path.remove(&project_path); self.opened_buffers.remove(&buffer_id);
self.local_buffer_ids_by_entry_id.remove(entry_id); self.local_buffer_ids_by_path.remove(&project_path);
continue; self.local_buffer_ids_by_entry_id.remove(entry_id);
}; continue;
};
buffer.update(cx, |buffer, cx| { buffer.update(cx, |buffer, cx| {
if let Some(old_file) = File::from_dyn(buffer.file()) { if let Some(old_file) = File::from_dyn(buffer.file()) {
@ -6640,7 +6662,7 @@ impl Project {
.opened_buffers .opened_buffers
.values() .values()
.filter_map(|buffer| { .filter_map(|buffer| {
let buffer = buffer.upgrade()?; let buffer = buffer.handle.upgrade()?;
let file = File::from_dyn(buffer.read(cx).file())?; let file = File::from_dyn(buffer.read(cx).file())?;
if file.worktree != worktree_handle { if file.worktree != worktree_handle {
return None; return None;
@ -6968,7 +6990,7 @@ impl Project {
if is_host { if is_host {
this.opened_buffers this.opened_buffers
.retain(|_, buffer| !matches!(buffer, OpenBuffer::Operations(_))); .retain(|_, buffer| !matches!(buffer.handle, BufferHandle::Operations(_)));
this.buffer_ordered_messages_tx this.buffer_ordered_messages_tx
.unbounded_send(BufferOrderedMessage::Resync) .unbounded_send(BufferOrderedMessage::Resync)
.unwrap(); .unwrap();
@ -7000,7 +7022,7 @@ impl Project {
.ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))? .ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))?
.replica_id; .replica_id;
for buffer in this.opened_buffers.values() { for buffer in this.opened_buffers.values() {
if let Some(buffer) = buffer.upgrade() { if let Some(buffer) = buffer.handle.upgrade() {
buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx)); buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx));
} }
} }
@ -7329,12 +7351,12 @@ impl Project {
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let is_remote = this.is_remote(); let is_remote = this.is_remote();
match this.opened_buffers.entry(buffer_id) { match this.opened_buffers.entry(buffer_id) {
hash_map::Entry::Occupied(mut e) => match e.get_mut() { hash_map::Entry::Occupied(mut e) => match &mut e.get_mut().handle {
OpenBuffer::Strong(buffer) => { BufferHandle::Strong(buffer) => {
buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))?; buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))?;
} }
OpenBuffer::Operations(operations) => operations.extend_from_slice(&ops), BufferHandle::Operations(operations) => operations.extend_from_slice(&ops),
OpenBuffer::Weak(_) => {} BufferHandle::Weak(_) => {}
}, },
hash_map::Entry::Vacant(e) => { hash_map::Entry::Vacant(e) => {
assert!( assert!(
@ -7342,7 +7364,10 @@ impl Project {
"received buffer update from {:?}", "received buffer update from {:?}",
envelope.original_sender_id envelope.original_sender_id
); );
e.insert(OpenBuffer::Operations(ops)); e.insert(OpenBuffer {
handle: BufferHandle::Operations(ops),
can_start_language_servers: false,
});
} }
} }
Ok(proto::Ack {}) Ok(proto::Ack {})
@ -7424,7 +7449,7 @@ impl Project {
if let Some(buffer) = this if let Some(buffer) = this
.opened_buffers .opened_buffers
.get_mut(&buffer_id) .get_mut(&buffer_id)
.and_then(|b| b.upgrade()) .and_then(|b| b.handle.upgrade())
.or_else(|| { .or_else(|| {
this.incomplete_remote_buffers this.incomplete_remote_buffers
.get(&buffer_id) .get(&buffer_id)
@ -7452,7 +7477,7 @@ impl Project {
if let Some(buffer) = this if let Some(buffer) = this
.opened_buffers .opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|b| b.upgrade()) .and_then(|b| b.handle.upgrade())
.or_else(|| { .or_else(|| {
this.incomplete_remote_buffers this.incomplete_remote_buffers
.get(&buffer_id) .get(&buffer_id)
@ -7486,7 +7511,7 @@ impl Project {
let buffer = this let buffer = this
.opened_buffers .opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?; .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?;
anyhow::Ok((project_id, buffer)) anyhow::Ok((project_id, buffer))
})??; })??;
@ -7522,7 +7547,7 @@ impl Project {
buffers.insert( buffers.insert(
this.opened_buffers this.opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?, .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?,
); );
} }
@ -7646,7 +7671,7 @@ impl Project {
buffers.insert( buffers.insert(
this.opened_buffers this.opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?, .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?,
); );
} }
@ -7674,7 +7699,7 @@ impl Project {
let buffer = this let buffer = this
.opened_buffers .opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?; .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?;
let language = buffer.read(cx).language(); let language = buffer.read(cx).language();
let completion = language::proto::deserialize_completion( let completion = language::proto::deserialize_completion(
@ -7753,7 +7778,7 @@ impl Project {
let buffer = this let buffer = this
.opened_buffers .opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?; .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
Ok::<_, anyhow::Error>(this.apply_code_action(buffer, action, false, cx)) Ok::<_, anyhow::Error>(this.apply_code_action(buffer, action, false, cx))
})??; })??;
@ -7778,7 +7803,7 @@ impl Project {
let buffer = this let buffer = this
.opened_buffers .opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?; .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?;
let position = envelope let position = envelope
.payload .payload
@ -7811,7 +7836,7 @@ impl Project {
let buffer = this.update(&mut cx, |this, _| { let buffer = this.update(&mut cx, |this, _| {
this.opened_buffers this.opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id)) .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))
})??; })??;
let buffer_version = deserialize_version(&envelope.payload.version); let buffer_version = deserialize_version(&envelope.payload.version);
@ -7867,7 +7892,7 @@ impl Project {
let buffer_id = BufferId::new(envelope.payload.buffer_id)?; let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
this.opened_buffers this.opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id)) .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))
})??; })??;
let response_hint = this let response_hint = this
@ -7913,7 +7938,7 @@ impl Project {
let buffer_handle = this.update(&mut cx, |this, _cx| { let buffer_handle = this.update(&mut cx, |this, _cx| {
this.opened_buffers this.opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id)) .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))
})??; })??;
let request = T::from_proto( let request = T::from_proto(
@ -8186,7 +8211,7 @@ impl Project {
let buffer = this.update(&mut cx, |this, _cx| { let buffer = this.update(&mut cx, |this, _cx| {
this.opened_buffers this.opened_buffers
.get(&id) .get(&id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
})?; })?;
if let Some(buffer) = buffer { if let Some(buffer) = buffer {
@ -8239,7 +8264,7 @@ impl Project {
.opened_buffers .opened_buffers
.iter() .iter()
.filter_map(|(id, buffer)| { .filter_map(|(id, buffer)| {
let buffer = buffer.upgrade()?; let buffer = buffer.handle.upgrade()?;
Some(proto::BufferVersion { Some(proto::BufferVersion {
id: (*id).into(), id: (*id).into(),
version: language::proto::serialize_version(&buffer.read(cx).version), version: language::proto::serialize_version(&buffer.read(cx).version),
@ -8457,7 +8482,7 @@ impl Project {
let buffer = this let buffer = this
.opened_buffers .opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.or_else(|| { .or_else(|| {
this.incomplete_remote_buffers this.incomplete_remote_buffers
.get(&buffer_id) .get(&buffer_id)
@ -8494,7 +8519,7 @@ impl Project {
let buffer = this let buffer = this
.opened_buffers .opened_buffers
.get(&buffer_id) .get(&buffer_id)
.and_then(|buffer| buffer.upgrade()) .and_then(|buffer| buffer.handle.upgrade())
.or_else(|| { .or_else(|| {
this.incomplete_remote_buffers this.incomplete_remote_buffers
.get(&buffer_id) .get(&buffer_id)
@ -8803,12 +8828,12 @@ impl WorktreeHandle {
} }
} }
impl OpenBuffer { impl BufferHandle {
pub fn upgrade(&self) -> Option<Model<Buffer>> { pub fn upgrade(&self) -> Option<Model<Buffer>> {
match self { match self {
OpenBuffer::Strong(handle) => Some(handle.clone()), BufferHandle::Strong(handle) => Some(handle.clone()),
OpenBuffer::Weak(handle) => handle.upgrade(), BufferHandle::Weak(handle) => handle.upgrade(),
OpenBuffer::Operations(_) => None, BufferHandle::Operations(_) => None,
} }
} }
} }

View file

@ -197,6 +197,7 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
"test2.rs": "", "test2.rs": "",
"Cargo.toml": "a = 1", "Cargo.toml": "a = 1",
"package.json": "{\"a\": 1}", "package.json": "{\"a\": 1}",
"package-lock.json": "{\"b\": 2}",
}), }),
) )
.await; .await;
@ -218,6 +219,18 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
}) })
.await .await
.unwrap(); .unwrap();
// Open a buffer that has an associated language server, but don't enable LSP for that buffer.
let json_buffer_without_lsp = project
.update(cx, |project, cx| {
project.open_local_buffer("/the-root/package-lock.json", cx)
})
.await
.unwrap();
project.update(cx, |project, cx| {
project.allow_buffer_to_start_language_servers(&toml_buffer, cx);
project.allow_buffer_to_start_language_servers(&rust_buffer, cx);
});
rust_buffer.update(cx, |buffer, _| { rust_buffer.update(cx, |buffer, _| {
assert_eq!(buffer.language().map(|l| l.name()), None); assert_eq!(buffer.language().map(|l| l.name()), None);
}); });
@ -234,7 +247,7 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
}); });
// A server is started up, and it is notified about Rust files. // A server is started up, and it is notified about Rust files.
let mut fake_rust_server = fake_rust_servers.next().await.unwrap(); let mut fake_rust_server = fake_rust_servers.try_next().unwrap().unwrap();
assert_eq!( assert_eq!(
fake_rust_server fake_rust_server
.receive_notification::<lsp::notification::DidOpenTextDocument>() .receive_notification::<lsp::notification::DidOpenTextDocument>()
@ -248,6 +261,8 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
} }
); );
assert!(fake_json_servers.try_next().is_err());
// The buffer is configured based on the language server's capabilities. // The buffer is configured based on the language server's capabilities.
rust_buffer.update(cx, |buffer, _| { rust_buffer.update(cx, |buffer, _| {
assert_eq!( assert_eq!(
@ -280,8 +295,13 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(); .unwrap();
project.update(cx, |project, cx| {
project.allow_buffer_to_start_language_servers(&json_buffer, cx);
});
cx.executor().run_until_parked();
// A json language server is started up and is only notified about the json buffer. // A json language server is started up and is only notified about the json buffer.
let mut fake_json_server = fake_json_servers.next().await.unwrap(); let mut fake_json_server = fake_json_servers.try_next().unwrap().unwrap();
assert_eq!( assert_eq!(
fake_json_server fake_json_server
.receive_notification::<lsp::notification::DidOpenTextDocument>() .receive_notification::<lsp::notification::DidOpenTextDocument>()
@ -294,6 +314,18 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
language_id: Default::default() language_id: Default::default()
} }
); );
assert_eq!(
fake_json_server
.receive_notification::<lsp::notification::DidOpenTextDocument>()
.await
.text_document,
lsp::TextDocumentItem {
uri: lsp::Url::from_file_path("/the-root/package-lock.json").unwrap(),
version: 0,
text: "{\"b\": 2}".to_string(),
language_id: Default::default()
}
);
// This buffer is configured based on the second language server's // This buffer is configured based on the second language server's
// capabilities. // capabilities.