Implement SemanticIndex::status and use it in project search

Co-Authored-By: Kyle Caverly <kyle@zed.dev>
This commit is contained in:
Antonio Scandurra 2023-09-07 19:39:30 +02:00
parent 47d7aa0b91
commit eda7e00645
2 changed files with 96 additions and 47 deletions

View file

@ -109,6 +109,13 @@ pub fn init(
.detach();
}
#[derive(Copy, Clone, Debug)]
pub enum SemanticIndexStatus {
NotIndexed,
Indexed,
Indexing { remaining_files: usize },
}
pub struct SemanticIndex {
fs: Arc<dyn Fs>,
db: VectorDatabase,
@ -124,7 +131,9 @@ struct ProjectState {
worktrees: HashMap<WorktreeId, WorktreeState>,
pending_file_count_rx: watch::Receiver<usize>,
pending_file_count_tx: Arc<Mutex<watch::Sender<usize>>>,
pending_index: usize,
_subscription: gpui::Subscription,
_observe_pending_file_count: Task<()>,
}
enum WorktreeState {
@ -133,6 +142,10 @@ enum WorktreeState {
}
impl WorktreeState {
fn is_registered(&self) -> bool {
matches!(self, Self::Registered(_))
}
fn paths_changed(
&mut self,
changes: Arc<[(Arc<Path>, ProjectEntryId, PathChange)]>,
@ -207,14 +220,25 @@ impl JobHandle {
}
impl ProjectState {
fn new(subscription: gpui::Subscription) -> Self {
fn new(subscription: gpui::Subscription, cx: &mut ModelContext<SemanticIndex>) -> Self {
let (pending_file_count_tx, pending_file_count_rx) = watch::channel_with(0);
let pending_file_count_tx = Arc::new(Mutex::new(pending_file_count_tx));
Self {
worktrees: Default::default(),
pending_file_count_rx,
pending_file_count_rx: pending_file_count_rx.clone(),
pending_file_count_tx,
pending_index: 0,
_subscription: subscription,
_observe_pending_file_count: cx.spawn_weak({
let mut pending_file_count_rx = pending_file_count_rx.clone();
|this, mut cx| async move {
while let Some(_) = pending_file_count_rx.next().await {
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |_, cx| cx.notify());
}
}
}
}),
}
}
@ -257,6 +281,25 @@ impl SemanticIndex {
&& *RELEASE_CHANNEL != ReleaseChannel::Stable
}
pub fn status(&self, project: &ModelHandle<Project>) -> SemanticIndexStatus {
if let Some(project_state) = self.projects.get(&project.downgrade()) {
if project_state
.worktrees
.values()
.all(|worktree| worktree.is_registered())
&& project_state.pending_index == 0
{
SemanticIndexStatus::Indexed
} else {
SemanticIndexStatus::Indexing {
remaining_files: project_state.pending_file_count_rx.borrow().clone(),
}
}
} else {
SemanticIndexStatus::NotIndexed
}
}
async fn new(
fs: Arc<dyn Fs>,
database_path: PathBuf,
@ -800,13 +843,15 @@ impl SemanticIndex {
}
_ => {}
});
self.projects
.insert(project.downgrade(), ProjectState::new(subscription));
let project_state = ProjectState::new(subscription, cx);
self.projects.insert(project.downgrade(), project_state);
self.project_worktrees_changed(project.clone(), cx);
}
let project_state = &self.projects[&project.downgrade()];
let mut pending_file_count_rx = project_state.pending_file_count_rx.clone();
let project_state = self.projects.get_mut(&project.downgrade()).unwrap();
project_state.pending_index += 1;
cx.notify();
let mut pending_file_count_rx = project_state.pending_file_count_rx.clone();
let db = self.db.clone();
let language_registry = self.language_registry.clone();
let parsing_files_tx = self.parsing_files_tx.clone();
@ -917,6 +962,16 @@ impl SemanticIndex {
})
.await;
this.update(&mut cx, |this, cx| {
let project_state = this
.projects
.get_mut(&project.downgrade())
.ok_or_else(|| anyhow!("project was dropped"))?;
project_state.pending_index -= 1;
cx.notify();
anyhow::Ok(())
})?;
Ok(())
})
}