diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index ca317c0ded71ab50ce46a1ec5f1af4a04a60991f..448735fe3c4856168713fcb75bea8ef60fd112e8 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -849,6 +849,7 @@ impl ProjectSearchView { let model = model.read(cx); project = model.project.clone(); SemanticIndex::global(cx).map(|semantic| { + dbg!("Initializing project"); semantic.update(cx, |this, cx| this.initialize_project(project.clone(), cx)); }); } diff --git a/crates/semantic_index/src/semantic_index.rs b/crates/semantic_index/src/semantic_index.rs index ffe6e74a6df05f10da53cbdf9ded64867823f941..0df3a9cc8428e37825c4e982525c3934e8efa8b3 100644 --- a/crates/semantic_index/src/semantic_index.rs +++ b/crates/semantic_index/src/semantic_index.rs @@ -156,7 +156,7 @@ impl ProjectState { fn update_queue(queue: &mut Vec, operation: IndexOperation) { match operation { IndexOperation::FlushQueue => { - for op in queue.pop() { + while let Some(op) = queue.pop() { match op { IndexOperation::IndexFile { payload, tx } => { tx.try_send(payload); @@ -652,51 +652,103 @@ impl SemanticIndex { }) } - // pub fn project_entries_changed( - // &self, - // project: ModelHandle, - // changes: &Arc<[(Arc, ProjectEntryId, PathChange)]>, - // cx: &ModelContext, - // worktree_id: &WorktreeId, - // ) -> Result<()> { - // let parsing_files_tx = self.parsing_files_tx.clone(); - // let db_update_tx = self.db_update_tx.clone(); - // let (job_queue_tx, outstanding_job_tx, worktree_db_id) = { - // let state = self.projects.get(&project.downgrade()); - // if state.is_none() { - // return anyhow::Error(anyhow!("Project not yet initialized")); - // } - // let state = state.unwrap(); - // ( - // state.job_queue_tx.clone(), - // state._outstanding_job_count_tx, - // state.db_id_for_worktree_id(worktree_id), - // ) - // }; - - // for (path, entry_id, path_change) in changes.iter() { - // match path_change { - // PathChange::AddedOrUpdated => { - // let job_handle = JobHandle::new(&outstanding_job_tx); - // job_queue_tx.try_send(IndexOperation::IndexFile { - // payload: PendingFile { - // worktree_db_id, - // relative_path: path, - // absolute_path, - // language, - // modified_time, - // job_handle, - // }, - // tx: parsing_files_tx, - // }) - // } - // PathChange::Removed => {} - // _ => {} - // } - // } - - // Ok(()) - // } + fn project_entries_changed( + &self, + project: ModelHandle, + changes: Arc<[(Arc, ProjectEntryId, PathChange)]>, + cx: &mut ModelContext<'_, SemanticIndex>, + worktree_id: &WorktreeId, + ) -> Result<()> { + let parsing_files_tx = self.parsing_files_tx.clone(); + let db_update_tx = self.db_update_tx.clone(); + let (job_queue_tx, outstanding_job_tx, worktree_db_id) = { + let state = self + .projects + .get(&project.downgrade()) + .ok_or(anyhow!("Project not yet initialized"))?; + let worktree_db_id = state + .db_id_for_worktree_id(*worktree_id) + .ok_or(anyhow!("Worktree ID in Database Not Available"))?; + ( + state.job_queue_tx.clone(), + state._outstanding_job_count_tx.clone(), + worktree_db_id, + ) + }; + + let language_registry = self.language_registry.clone(); + let parsing_files_tx = parsing_files_tx.clone(); + let db_update_tx = db_update_tx.clone(); + + let worktree = project + .read(cx) + .worktree_for_id(worktree_id.clone(), cx) + .ok_or(anyhow!("Worktree not available"))? + .read(cx) + .snapshot(); + cx.spawn(|this, mut cx| async move { + let worktree = worktree.clone(); + for (path, entry_id, path_change) in changes.iter() { + let relative_path = path.to_path_buf(); + let absolute_path = worktree.absolutize(path); + + let Some(entry) = worktree.entry_for_id(*entry_id) else { + continue; + }; + if entry.is_ignored || entry.is_symlink || entry.is_external { + continue; + } + + match path_change { + PathChange::AddedOrUpdated | PathChange::Updated => { + log::trace!("File Updated: {:?}", path); + if let Ok(language) = language_registry + .language_for_file(&relative_path, None) + .await + { + if !PARSEABLE_ENTIRE_FILE_TYPES.contains(&language.name().as_ref()) + && &language.name().as_ref() != &"Markdown" + && language + .grammar() + .and_then(|grammar| grammar.embedding_config.as_ref()) + .is_none() + { + continue; + } + + let job_handle = JobHandle::new(&outstanding_job_tx); + let new_operation = IndexOperation::IndexFile { + payload: PendingFile { + worktree_db_id, + relative_path, + absolute_path, + language, + modified_time: entry.mtime, + job_handle, + }, + tx: parsing_files_tx.clone(), + }; + job_queue_tx.try_send(new_operation); + } + } + PathChange::Removed => { + let new_operation = IndexOperation::DeleteFile { + payload: DbOperation::Delete { + worktree_id: worktree_db_id, + path: relative_path, + }, + tx: db_update_tx.clone(), + }; + job_queue_tx.try_send(new_operation); + } + _ => {} + } + } + }) + .detach(); + + Ok(()) + } pub fn initialize_project( &mut self, @@ -724,9 +776,8 @@ impl SemanticIndex { let _subscription = cx.subscribe(&project, |this, project, event, cx| { if let project::Event::WorktreeUpdatedEntries(worktree_id, changes) = event { - todo!(); - // this.project_entries_changed(project, changes, cx, worktree_id); - } + this.project_entries_changed(project, changes.clone(), cx, worktree_id); + }; }); let language_registry = self.language_registry.clone(); @@ -775,6 +826,10 @@ impl SemanticIndex { for file in worktree.files(false, 0) { let absolute_path = worktree.absolutize(&file.path); + if file.is_external || file.is_ignored || file.is_symlink { + continue; + } + if let Ok(language) = language_registry .language_for_file(&absolute_path, None) .await @@ -827,10 +882,8 @@ impl SemanticIndex { job_count_tx_longlived, ); - if let Some(project_state) = this.projects.get_mut(&project.downgrade()) { - for op in worktree_files { - project_state.job_queue_tx.try_send(op); - } + for op in worktree_files { + project_state.job_queue_tx.try_send(op); } this.projects.insert(project.downgrade(), project_state); @@ -864,10 +917,10 @@ impl SemanticIndex { return; }; state.job_queue_tx.try_send(IndexOperation::FlushQueue); - }) - }); + }); - Task::Ready(Some(Ok((count, job_count_rx)))) + Ok((count, job_count_rx)) + }) } pub fn outstanding_job_count_rx(