mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
wip
This commit is contained in:
parent
20b7f31e7d
commit
5348e0511b
5 changed files with 221 additions and 2 deletions
|
|
@ -530,9 +530,18 @@ pub struct RealFs {
|
|||
|
||||
pub trait FileHandle: Send + Sync + std::fmt::Debug {
|
||||
fn current_path(&self, fs: &Arc<dyn Fs>) -> Result<PathBuf>;
|
||||
|
||||
fn debug_fd(&self) -> Option<i64> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl FileHandle for std::fs::File {
|
||||
#[cfg(unix)]
|
||||
fn debug_fd(&self) -> Option<i64> {
|
||||
Some(self.as_raw_fd().into())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn current_path(&self, _: &Arc<dyn Fs>) -> Result<PathBuf> {
|
||||
use std::{
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ use gpui::{
|
|||
WeakEntity,
|
||||
};
|
||||
use language::{
|
||||
Buffer, BufferEvent, Capability, DiskState, File as _, Language, LineEnding, Operation,
|
||||
Buffer, BufferEvent, Capability, DiskState, File as _, Language, LineEnding, LocalFile as _,
|
||||
Operation,
|
||||
language_settings::{AllLanguageSettings, LineEndingSetting},
|
||||
proto::{
|
||||
deserialize_line_ending, deserialize_version, serialize_line_ending, serialize_version,
|
||||
|
|
@ -963,7 +964,21 @@ impl BufferStore {
|
|||
path: file.path.clone(),
|
||||
worktree_id: file.worktree_id(cx),
|
||||
});
|
||||
let file = File::from_dyn(buffer.file()).cloned();
|
||||
let is_remote = buffer.replica_id().is_remote();
|
||||
log::debug!(
|
||||
"adding buffer entity_id={:?}, buffer_id={:?}, path={:?}, worktree_id={:?}, worktree_visible={:?}, worktree_single_file={:?}, root_file_handle_fd={:?}",
|
||||
buffer_entity.entity_id(),
|
||||
remote_id,
|
||||
file.as_ref().map(|file| file.abs_path(cx)),
|
||||
file.as_ref().map(|file| file.worktree_id(cx)),
|
||||
file.as_ref()
|
||||
.map(|file| file.worktree.read(cx).is_visible()),
|
||||
file.as_ref()
|
||||
.map(|file| file.worktree.read(cx).is_single_file()),
|
||||
file.as_ref()
|
||||
.and_then(|file| file.worktree.read(cx).root_file_handle_debug_fd())
|
||||
);
|
||||
let open_buffer = OpenBuffer::Complete {
|
||||
buffer: buffer_entity.downgrade(),
|
||||
};
|
||||
|
|
@ -971,6 +986,17 @@ impl BufferStore {
|
|||
let handle = cx.entity().downgrade();
|
||||
buffer_entity.update(cx, move |_, cx| {
|
||||
cx.on_release(move |buffer, cx| {
|
||||
let file = File::from_dyn(buffer.file()).cloned();
|
||||
log::debug!(
|
||||
"buffer released buffer_id={:?}, path={:?}, worktree_id={:?}, worktree_visible={:?}, worktree_single_file={:?}, root_file_handle_fd={:?}",
|
||||
buffer.remote_id(),
|
||||
file.as_ref().map(|file| file.abs_path(cx)),
|
||||
file.as_ref().map(|file| file.worktree_id(cx)),
|
||||
file.as_ref().map(|file| file.worktree.read(cx).is_visible()),
|
||||
file.as_ref().map(|file| file.worktree.read(cx).is_single_file()),
|
||||
file.as_ref()
|
||||
.and_then(|file| file.worktree.read(cx).root_file_handle_debug_fd())
|
||||
);
|
||||
handle
|
||||
.update(cx, |_, cx| {
|
||||
cx.emit(BufferStoreEvent::BufferDropped(buffer.remote_id()))
|
||||
|
|
|
|||
|
|
@ -2784,6 +2784,15 @@ impl LocalLspStore {
|
|||
let Some(file) = File::from_dyn(buffer.file()) else {
|
||||
return;
|
||||
};
|
||||
log::debug!(
|
||||
"registering buffer with language servers buffer_id={:?}, path={:?}, worktree_id={:?}, worktree_visible={}, worktree_single_file={}, root_file_handle_fd={:?}",
|
||||
buffer_id,
|
||||
file.abs_path(cx),
|
||||
file.worktree_id(cx),
|
||||
file.worktree.read(cx).is_visible(),
|
||||
file.worktree.read(cx).is_single_file(),
|
||||
file.worktree.read(cx).root_file_handle_debug_fd()
|
||||
);
|
||||
if !file.is_local() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -2883,6 +2892,13 @@ impl LocalLspStore {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
log::debug!(
|
||||
"selected language servers for buffer buffer_id={:?}, path={:?}, server_count={}, reused={}",
|
||||
buffer_id,
|
||||
abs_path,
|
||||
servers_and_adapters.len(),
|
||||
reused
|
||||
);
|
||||
for (server, adapter) in servers_and_adapters {
|
||||
buffer_handle.update(cx, |buffer, cx| {
|
||||
buffer.set_completion_triggers(
|
||||
|
|
@ -3027,6 +3043,18 @@ impl LocalLspStore {
|
|||
cx: &mut App,
|
||||
) {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
let file = File::from_dyn(buffer.file()).cloned();
|
||||
log::debug!(
|
||||
"unregistering buffer from language servers buffer_id={:?}, path={:?}, worktree_id={:?}, worktree_visible={:?}, worktree_single_file={:?}, root_file_handle_fd={:?}, uri={}",
|
||||
buffer.remote_id(),
|
||||
file.as_ref().map(|file| file.abs_path(cx)),
|
||||
file.as_ref().map(|file| file.worktree_id(cx)),
|
||||
file.as_ref().map(|file| file.worktree.read(cx).is_visible()),
|
||||
file.as_ref().map(|file| file.worktree.read(cx).is_single_file()),
|
||||
file.as_ref()
|
||||
.and_then(|file| file.worktree.read(cx).root_file_handle_debug_fd()),
|
||||
file_url
|
||||
);
|
||||
let mut snapshots = self.buffer_snapshots.remove(&buffer.remote_id());
|
||||
|
||||
for (_, language_server) in self.language_servers_for_buffer(buffer, cx) {
|
||||
|
|
@ -4614,6 +4642,21 @@ impl LspStore {
|
|||
) -> OpenLspBufferHandle {
|
||||
let buffer_id = buffer.read(cx).remote_id();
|
||||
let handle = OpenLspBufferHandle(cx.new(|_| OpenLspBuffer(buffer.clone())));
|
||||
let file = File::from_dyn(buffer.read(cx).file()).cloned();
|
||||
log::debug!(
|
||||
"creating open lsp buffer handle entity_id={:?}, buffer_id={:?}, path={:?}, worktree_id={:?}, worktree_visible={:?}, worktree_single_file={:?}, root_file_handle_fd={:?}, ignore_refcounts={}",
|
||||
handle.0.entity_id(),
|
||||
buffer_id,
|
||||
file.as_ref().map(|file| file.abs_path(cx)),
|
||||
file.as_ref().map(|file| file.worktree_id(cx)),
|
||||
file.as_ref()
|
||||
.map(|file| file.worktree.read(cx).is_visible()),
|
||||
file.as_ref()
|
||||
.map(|file| file.worktree.read(cx).is_single_file()),
|
||||
file.as_ref()
|
||||
.and_then(|file| file.worktree.read(cx).root_file_handle_debug_fd()),
|
||||
ignore_refcounts
|
||||
);
|
||||
if let Some(local) = self.as_local_mut() {
|
||||
let refcount = local.registered_buffers.entry(buffer_id).or_insert(0);
|
||||
if !ignore_refcounts {
|
||||
|
|
@ -4636,6 +4679,18 @@ impl LspStore {
|
|||
}
|
||||
if !ignore_refcounts {
|
||||
cx.observe_release(&handle.0, move |lsp_store, buffer, cx| {
|
||||
let file = File::from_dyn(buffer.0.read(cx).file()).cloned();
|
||||
log::debug!(
|
||||
"open lsp buffer handle released entity_id={:?}, buffer_id={:?}, path={:?}, worktree_id={:?}, worktree_visible={:?}, worktree_single_file={:?}, root_file_handle_fd={:?}",
|
||||
buffer.0.entity_id(),
|
||||
buffer_id,
|
||||
file.as_ref().map(|file| file.abs_path(cx)),
|
||||
file.as_ref().map(|file| file.worktree_id(cx)),
|
||||
file.as_ref().map(|file| file.worktree.read(cx).is_visible()),
|
||||
file.as_ref().map(|file| file.worktree.read(cx).is_single_file()),
|
||||
file.as_ref()
|
||||
.and_then(|file| file.worktree.read(cx).root_file_handle_debug_fd())
|
||||
);
|
||||
let refcount = {
|
||||
let local = lsp_store.as_local_mut().unwrap();
|
||||
let Some(refcount) = local.registered_buffers.get_mut(&buffer_id) else {
|
||||
|
|
@ -4646,6 +4701,11 @@ impl LspStore {
|
|||
*refcount -= 1;
|
||||
*refcount
|
||||
};
|
||||
log::debug!(
|
||||
"open lsp buffer handle refcount after release buffer_id={:?}, refcount={}",
|
||||
buffer_id,
|
||||
refcount
|
||||
);
|
||||
if refcount == 0 {
|
||||
lsp_store.lsp_data.remove(&buffer_id);
|
||||
lsp_store.buffer_reload_tasks.remove(&buffer_id);
|
||||
|
|
|
|||
|
|
@ -888,6 +888,16 @@ impl WorktreeStore {
|
|||
} else {
|
||||
WorktreeHandle::Weak(worktree.downgrade())
|
||||
};
|
||||
log::debug!(
|
||||
"adding worktree entity_id={:?}, worktree_id={:?}, path={:?}, visible={}, single_file={}, retained_strongly={}, root_file_handle_fd={:?}",
|
||||
worktree.entity_id(),
|
||||
worktree_id,
|
||||
worktree.read(cx).abs_path(),
|
||||
worktree.read(cx).is_visible(),
|
||||
worktree.read(cx).is_single_file(),
|
||||
push_strong_handle,
|
||||
worktree.read(cx).root_file_handle_debug_fd()
|
||||
);
|
||||
self.worktrees.push(handle);
|
||||
|
||||
cx.emit(WorktreeStoreEvent::WorktreeAdded(worktree.clone()));
|
||||
|
|
@ -925,6 +935,15 @@ impl WorktreeStore {
|
|||
})
|
||||
.detach();
|
||||
cx.observe_release(worktree, move |this, worktree, cx| {
|
||||
log::debug!(
|
||||
"worktree released entity_id={:?}, worktree_id={:?}, path={:?}, visible={}, single_file={}, root_file_handle_fd={:?}",
|
||||
handle_id,
|
||||
worktree.id(),
|
||||
worktree.abs_path(),
|
||||
worktree.is_visible(),
|
||||
worktree.is_single_file(),
|
||||
worktree.root_file_handle_debug_fd()
|
||||
);
|
||||
cx.emit(WorktreeStoreEvent::WorktreeReleased(
|
||||
handle_id,
|
||||
worktree.id(),
|
||||
|
|
@ -942,6 +961,15 @@ impl WorktreeStore {
|
|||
self.worktrees.retain(|worktree| {
|
||||
if let Some(worktree) = worktree.upgrade() {
|
||||
if worktree.read(cx).id() == id_to_remove {
|
||||
log::debug!(
|
||||
"removing worktree entity_id={:?}, worktree_id={:?}, path={:?}, visible={}, single_file={}, root_file_handle_fd={:?}",
|
||||
worktree.entity_id(),
|
||||
id_to_remove,
|
||||
worktree.read(cx).abs_path(),
|
||||
worktree.read(cx).is_visible(),
|
||||
worktree.read(cx).is_single_file(),
|
||||
worktree.read(cx).root_file_handle_debug_fd()
|
||||
);
|
||||
cx.emit(WorktreeStoreEvent::WorktreeRemoved(
|
||||
worktree.entity_id(),
|
||||
id_to_remove,
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ use std::{
|
|||
future::Future,
|
||||
mem::{self},
|
||||
ops::{Deref, DerefMut, Range},
|
||||
panic::Location,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
sync::{
|
||||
|
|
@ -150,6 +151,7 @@ pub struct PathPrefixScanRequest {
|
|||
|
||||
struct ScanRequest {
|
||||
relative_paths: Vec<Arc<RelPath>>,
|
||||
trigger_locations: SmallVec<[&'static Location<'static>; 1]>,
|
||||
done: SmallVec<[barrier::Sender; 1]>,
|
||||
}
|
||||
|
||||
|
|
@ -258,6 +260,34 @@ pub struct LocalSnapshot {
|
|||
root_file_handle: Option<Arc<dyn fs::FileHandle>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RootFileHandle {
|
||||
inner: Arc<dyn fs::FileHandle>,
|
||||
path: Arc<Path>,
|
||||
worktree_id: WorktreeId,
|
||||
}
|
||||
|
||||
impl fs::FileHandle for RootFileHandle {
|
||||
fn current_path(&self, fs: &Arc<dyn Fs>) -> Result<PathBuf> {
|
||||
self.inner.current_path(fs)
|
||||
}
|
||||
|
||||
fn debug_fd(&self) -> Option<i64> {
|
||||
self.inner.debug_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RootFileHandle {
|
||||
fn drop(&mut self) {
|
||||
log::debug!(
|
||||
"dropping root file handle worktree_id={:?}, path={:?}, root_file_handle_fd={:?}",
|
||||
self.worktree_id,
|
||||
self.path,
|
||||
self.inner.debug_fd()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct BackgroundScannerState {
|
||||
snapshot: LocalSnapshot,
|
||||
symlink_paths_by_target: HashMap<Arc<Path>, SmallVec<[Arc<RelPath>; 1]>>,
|
||||
|
|
@ -411,9 +441,26 @@ impl Worktree {
|
|||
)
|
||||
})
|
||||
.log_err()
|
||||
.map(|inner| {
|
||||
Arc::new(RootFileHandle {
|
||||
inner,
|
||||
path: abs_path.clone(),
|
||||
worktree_id,
|
||||
}) as Arc<dyn fs::FileHandle>
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
log::debug!(
|
||||
"created local worktree root handle path={:?}, visible={}, is_single_file={}, root_file_handle_fd={:?}, worktree_id={:?}",
|
||||
abs_path,
|
||||
visible,
|
||||
metadata.as_ref().is_some_and(|metadata| !metadata.is_dir),
|
||||
root_file_handle
|
||||
.as_ref()
|
||||
.and_then(|handle| handle.debug_fd()),
|
||||
worktree_id
|
||||
);
|
||||
|
||||
let root_repo_common_dir = if visible {
|
||||
discover_root_repo_common_dir(&abs_path, fs.as_ref())
|
||||
|
|
@ -739,6 +786,13 @@ impl Worktree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn root_file_handle_debug_fd(&self) -> Option<i64> {
|
||||
match self {
|
||||
Worktree::Local(worktree) => worktree.root_file_handle_debug_fd(),
|
||||
Worktree::Remote(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_file(&self, cx: &Context<Self>) -> Option<Arc<File>> {
|
||||
let entry = self.root_entry()?;
|
||||
Some(File::for_entry(entry.clone(), cx.entity()))
|
||||
|
|
@ -1111,11 +1165,31 @@ impl Worktree {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for LocalWorktree {
|
||||
fn drop(&mut self) {
|
||||
log::debug!(
|
||||
"dropping local worktree worktree_id={:?}, path={:?}, visible={}, single_file={}, root_file_handle_fd={:?}",
|
||||
self.snapshot.id(),
|
||||
self.snapshot.abs_path,
|
||||
self.visible,
|
||||
self.snapshot.root_dir().is_none(),
|
||||
self.root_file_handle_debug_fd()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalWorktree {
|
||||
pub fn fs(&self) -> &Arc<dyn Fs> {
|
||||
&self.fs
|
||||
}
|
||||
|
||||
pub fn root_file_handle_debug_fd(&self) -> Option<i64> {
|
||||
self.snapshot
|
||||
.root_file_handle
|
||||
.as_ref()
|
||||
.and_then(|handle| handle.debug_fd())
|
||||
}
|
||||
|
||||
pub fn is_path_private(&self, path: &RelPath) -> bool {
|
||||
!self.share_private_files && self.settings.is_path_private(path)
|
||||
}
|
||||
|
|
@ -1924,11 +1998,13 @@ impl LocalWorktree {
|
|||
}))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn refresh_entries_for_paths(&self, paths: Vec<Arc<RelPath>>) -> barrier::Receiver {
|
||||
let (tx, rx) = barrier::channel();
|
||||
self.scan_requests_tx
|
||||
.try_send(ScanRequest {
|
||||
relative_paths: paths,
|
||||
trigger_locations: smallvec![Location::caller()],
|
||||
done: smallvec![tx],
|
||||
})
|
||||
.ok();
|
||||
|
|
@ -4210,7 +4286,24 @@ impl BackgroundScanner {
|
|||
}
|
||||
|
||||
async fn process_scan_request(&self, mut request: ScanRequest, scanning: bool) -> bool {
|
||||
log::debug!("rescanning paths {:?}", request.relative_paths);
|
||||
let trigger_locations = request
|
||||
.trigger_locations
|
||||
.iter()
|
||||
.map(|location| {
|
||||
format!(
|
||||
"{}:{}:{}",
|
||||
location.file(),
|
||||
location.line(),
|
||||
location.column()
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
log::debug!(
|
||||
"rescanning paths {:?}, requested from {:?}, single_file_worktree={}",
|
||||
request.relative_paths,
|
||||
trigger_locations,
|
||||
self.is_single_file
|
||||
);
|
||||
|
||||
request.relative_paths.sort_unstable();
|
||||
self.forcibly_load_paths(&request.relative_paths).await;
|
||||
|
|
@ -5572,6 +5665,9 @@ impl BackgroundScanner {
|
|||
let mut request = self.scan_requests_rx.recv().await?;
|
||||
while let Ok(next_request) = self.scan_requests_rx.try_recv() {
|
||||
request.relative_paths.extend(next_request.relative_paths);
|
||||
request
|
||||
.trigger_locations
|
||||
.extend(next_request.trigger_locations);
|
||||
request.done.extend(next_request.done);
|
||||
}
|
||||
Ok(request)
|
||||
|
|
|
|||
Loading…
Reference in a new issue