Remove 2 suffix for fs, db, semantic_index, prettier

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-01-03 12:09:08 -08:00
parent 324ac96977
commit 5ddd298b4d
75 changed files with 455 additions and 12973 deletions

View file

@ -11,16 +11,13 @@ doctest = false
[dependencies]
ai = { path = "../ai" }
collections = { path = "../collections" }
gpui = { path = "../gpui" }
gpui = { package = "gpui2", path = "../gpui2" }
language = { path = "../language" }
project = { path = "../project" }
workspace = { path = "../workspace" }
util = { path = "../util" }
picker = { path = "../picker" }
theme = { path = "../theme" }
editor = { path = "../editor" }
rpc = { path = "../rpc" }
settings = { path = "../settings" }
settings = { package = "settings2", path = "../settings2" }
anyhow.workspace = true
postage.workspace = true
futures.workspace = true
@ -44,12 +41,12 @@ ndarray = { version = "0.15.0" }
[dev-dependencies]
ai = { path = "../ai", features = ["test-support"] }
collections = { path = "../collections", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] }
gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
language = { path = "../language", features = ["test-support"] }
project = { path = "../project", features = ["test-support"] }
rpc = { path = "../rpc", features = ["test-support"] }
workspace = { path = "../workspace", features = ["test-support"] }
settings = { path = "../settings", features = ["test-support"]}
settings = { package = "settings2", path = "../settings2", features = ["test-support"]}
rust-embed = { version = "8.0", features = ["include-exclude"] }
client = { path = "../client" }
node_runtime = { path = "../node_runtime"}

View file

@ -6,7 +6,7 @@ use ai::embedding::Embedding;
use anyhow::{anyhow, Context, Result};
use collections::HashMap;
use futures::channel::oneshot;
use gpui::executor;
use gpui::BackgroundExecutor;
use ndarray::{Array1, Array2};
use ordered_float::OrderedFloat;
use project::Fs;
@ -48,7 +48,7 @@ impl VectorDatabase {
pub async fn new(
fs: Arc<dyn Fs>,
path: Arc<Path>,
executor: Arc<executor::Background>,
executor: BackgroundExecutor,
) -> Result<Self> {
if let Some(db_directory) = path.parent() {
fs.create_dir(db_directory).await?;

View file

@ -1,6 +1,6 @@
use crate::{parsing::Span, JobHandle};
use ai::embedding::EmbeddingProvider;
use gpui::executor::Background;
use gpui::BackgroundExecutor;
use parking_lot::Mutex;
use smol::channel;
use std::{mem, ops::Range, path::Path, sync::Arc, time::SystemTime};
@ -37,7 +37,7 @@ impl PartialEq for FileToEmbed {
pub struct EmbeddingQueue {
embedding_provider: Arc<dyn EmbeddingProvider>,
pending_batch: Vec<FileFragmentToEmbed>,
executor: Arc<Background>,
executor: BackgroundExecutor,
pending_batch_token_count: usize,
finished_files_tx: channel::Sender<FileToEmbed>,
finished_files_rx: channel::Receiver<FileToEmbed>,
@ -50,7 +50,10 @@ pub struct FileFragmentToEmbed {
}
impl EmbeddingQueue {
pub fn new(embedding_provider: Arc<dyn EmbeddingProvider>, executor: Arc<Background>) -> Self {
pub fn new(
embedding_provider: Arc<dyn EmbeddingProvider>,
executor: BackgroundExecutor,
) -> Self {
let (finished_files_tx, finished_files_rx) = channel::unbounded();
Self {
embedding_provider,

View file

@ -9,12 +9,15 @@ mod semantic_index_tests;
use crate::semantic_index_settings::SemanticIndexSettings;
use ai::embedding::{Embedding, EmbeddingProvider};
use ai::providers::open_ai::OpenAIEmbeddingProvider;
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context as _, Result};
use collections::{BTreeMap, HashMap, HashSet};
use db::VectorDatabase;
use embedding_queue::{EmbeddingQueue, FileToEmbed};
use futures::{future, FutureExt, StreamExt};
use gpui::{AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Task, WeakModelHandle};
use gpui::{
AppContext, AsyncAppContext, BorrowWindow, Context, Model, ModelContext, Task, ViewContext,
WeakModel,
};
use language::{Anchor, Bias, Buffer, Language, LanguageRegistry};
use lazy_static::lazy_static;
use ordered_float::OrderedFloat;
@ -22,6 +25,7 @@ use parking_lot::Mutex;
use parsing::{CodeContextRetriever, Span, SpanDigest, PARSEABLE_ENTIRE_FILE_TYPES};
use postage::watch;
use project::{Fs, PathChange, Project, ProjectEntryId, Worktree, WorktreeId};
use settings::Settings;
use smol::channel;
use std::{
cmp::Reverse,
@ -35,7 +39,7 @@ use std::{
};
use util::paths::PathMatcher;
use util::{channel::RELEASE_CHANNEL_NAME, http::HttpClient, paths::EMBEDDINGS_DIR, ResultExt};
use workspace::WorkspaceCreated;
use workspace::Workspace;
const SEMANTIC_INDEX_VERSION: usize = 11;
const BACKGROUND_INDEXING_DELAY: Duration = Duration::from_secs(5 * 60);
@ -51,54 +55,54 @@ pub fn init(
language_registry: Arc<LanguageRegistry>,
cx: &mut AppContext,
) {
settings::register::<SemanticIndexSettings>(cx);
SemanticIndexSettings::register(cx);
let db_file_path = EMBEDDINGS_DIR
.join(Path::new(RELEASE_CHANNEL_NAME.as_str()))
.join("embeddings_db");
cx.subscribe_global::<WorkspaceCreated, _>({
move |event, cx| {
cx.observe_new_views(
|workspace: &mut Workspace, cx: &mut ViewContext<Workspace>| {
let Some(semantic_index) = SemanticIndex::global(cx) else {
return;
};
let workspace = &event.0;
if let Some(workspace) = workspace.upgrade(cx) {
let project = workspace.read(cx).project().clone();
if project.read(cx).is_local() {
cx.spawn(|mut cx| async move {
let project = workspace.project().clone();
if project.read(cx).is_local() {
cx.app_mut()
.spawn(|mut cx| async move {
let previously_indexed = semantic_index
.update(&mut cx, |index, cx| {
index.project_previously_indexed(&project, cx)
})
})?
.await?;
if previously_indexed {
semantic_index
.update(&mut cx, |index, cx| index.index_project(project, cx))
.update(&mut cx, |index, cx| index.index_project(project, cx))?
.await?;
}
anyhow::Ok(())
})
.detach_and_log_err(cx);
}
}
}
})
},
)
.detach();
cx.spawn(move |mut cx| async move {
cx.spawn(move |cx| async move {
let semantic_index = SemanticIndex::new(
fs,
db_file_path,
Arc::new(OpenAIEmbeddingProvider::new(http_client, cx.background())),
Arc::new(OpenAIEmbeddingProvider::new(
http_client,
cx.background_executor().clone(),
)),
language_registry,
cx.clone(),
)
.await?;
cx.update(|cx| {
cx.set_global(semantic_index.clone());
});
cx.update(|cx| cx.set_global(semantic_index.clone()))?;
anyhow::Ok(())
})
@ -124,7 +128,7 @@ pub struct SemanticIndex {
parsing_files_tx: channel::Sender<(Arc<HashMap<SpanDigest, Embedding>>, PendingFile)>,
_embedding_task: Task<()>,
_parsing_files_tasks: Vec<Task<()>>,
projects: HashMap<WeakModelHandle<Project>, ProjectState>,
projects: HashMap<WeakModel<Project>, ProjectState>,
}
struct ProjectState {
@ -229,12 +233,12 @@ impl ProjectState {
pending_file_count_tx,
pending_index: 0,
_subscription: subscription,
_observe_pending_file_count: cx.spawn_weak({
_observe_pending_file_count: cx.spawn({
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());
if this.update(&mut cx, |_, cx| cx.notify()).is_err() {
break;
}
}
}
@ -264,21 +268,21 @@ pub struct PendingFile {
#[derive(Clone)]
pub struct SearchResult {
pub buffer: ModelHandle<Buffer>,
pub buffer: Model<Buffer>,
pub range: Range<Anchor>,
pub similarity: OrderedFloat<f32>,
}
impl SemanticIndex {
pub fn global(cx: &mut AppContext) -> Option<ModelHandle<SemanticIndex>> {
if cx.has_global::<ModelHandle<Self>>() {
Some(cx.global::<ModelHandle<SemanticIndex>>().clone())
pub fn global(cx: &mut AppContext) -> Option<Model<SemanticIndex>> {
if cx.has_global::<Model<Self>>() {
Some(cx.global::<Model<SemanticIndex>>().clone())
} else {
None
}
}
pub fn authenticate(&mut self, cx: &AppContext) -> bool {
pub fn authenticate(&mut self, cx: &mut AppContext) -> bool {
if !self.embedding_provider.has_credentials() {
self.embedding_provider.retrieve_credentials(cx);
} else {
@ -293,10 +297,10 @@ impl SemanticIndex {
}
pub fn enabled(cx: &AppContext) -> bool {
settings::get::<SemanticIndexSettings>(cx).enabled
SemanticIndexSettings::get_global(cx).enabled
}
pub fn status(&self, project: &ModelHandle<Project>) -> SemanticIndexStatus {
pub fn status(&self, project: &Model<Project>) -> SemanticIndexStatus {
if !self.is_authenticated() {
return SemanticIndexStatus::NotAuthenticated;
}
@ -326,21 +330,22 @@ impl SemanticIndex {
embedding_provider: Arc<dyn EmbeddingProvider>,
language_registry: Arc<LanguageRegistry>,
mut cx: AsyncAppContext,
) -> Result<ModelHandle<Self>> {
) -> Result<Model<Self>> {
let t0 = Instant::now();
let database_path = Arc::from(database_path);
let db = VectorDatabase::new(fs.clone(), database_path, cx.background()).await?;
let db = VectorDatabase::new(fs.clone(), database_path, cx.background_executor().clone())
.await?;
log::trace!(
"db initialization took {:?} milliseconds",
t0.elapsed().as_millis()
);
Ok(cx.add_model(|cx| {
cx.new_model(|cx| {
let t0 = Instant::now();
let embedding_queue =
EmbeddingQueue::new(embedding_provider.clone(), cx.background().clone());
let _embedding_task = cx.background().spawn({
EmbeddingQueue::new(embedding_provider.clone(), cx.background_executor().clone());
let _embedding_task = cx.background_executor().spawn({
let embedded_files = embedding_queue.finished_files();
let db = db.clone();
async move {
@ -357,13 +362,13 @@ impl SemanticIndex {
channel::unbounded::<(Arc<HashMap<SpanDigest, Embedding>>, PendingFile)>();
let embedding_queue = Arc::new(Mutex::new(embedding_queue));
let mut _parsing_files_tasks = Vec::new();
for _ in 0..cx.background().num_cpus() {
for _ in 0..cx.background_executor().num_cpus() {
let fs = fs.clone();
let mut parsing_files_rx = parsing_files_rx.clone();
let embedding_provider = embedding_provider.clone();
let embedding_queue = embedding_queue.clone();
let background = cx.background().clone();
_parsing_files_tasks.push(cx.background().spawn(async move {
let background = cx.background_executor().clone();
_parsing_files_tasks.push(cx.background_executor().spawn(async move {
let mut retriever = CodeContextRetriever::new(embedding_provider.clone());
loop {
let mut timer = background.timer(EMBEDDING_QUEUE_FLUSH_TIMEOUT).fuse();
@ -405,7 +410,7 @@ impl SemanticIndex {
_parsing_files_tasks,
projects: Default::default(),
}
}))
})
}
async fn parse_file(
@ -449,12 +454,12 @@ impl SemanticIndex {
pub fn project_previously_indexed(
&mut self,
project: &ModelHandle<Project>,
project: &Model<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<bool>> {
let worktrees_indexed_previously = project
.read(cx)
.worktrees(cx)
.worktrees()
.map(|worktree| {
self.db
.worktree_previously_indexed(&worktree.read(cx).abs_path())
@ -473,7 +478,7 @@ impl SemanticIndex {
fn project_entries_changed(
&mut self,
project: ModelHandle<Project>,
project: Model<Project>,
worktree_id: WorktreeId,
changes: Arc<[(Arc<Path>, ProjectEntryId, PathChange)]>,
cx: &mut ModelContext<Self>,
@ -495,22 +500,25 @@ impl SemanticIndex {
};
worktree_state.paths_changed(changes, worktree);
if let WorktreeState::Registered(_) = worktree_state {
cx.spawn_weak(|this, mut cx| async move {
cx.background().timer(BACKGROUND_INDEXING_DELAY).await;
if let Some((this, project)) = this.upgrade(&cx).zip(project.upgrade(&cx)) {
cx.spawn(|this, mut cx| async move {
cx.background_executor()
.timer(BACKGROUND_INDEXING_DELAY)
.await;
if let Some((this, project)) = this.upgrade().zip(project.upgrade()) {
this.update(&mut cx, |this, cx| {
this.index_project(project, cx).detach_and_log_err(cx)
});
})?;
}
anyhow::Ok(())
})
.detach();
.detach_and_log_err(cx);
}
}
fn register_worktree(
&mut self,
project: ModelHandle<Project>,
worktree: ModelHandle<Worktree>,
project: Model<Project>,
worktree: Model<Worktree>,
cx: &mut ModelContext<Self>,
) {
let project = project.downgrade();
@ -536,16 +544,18 @@ impl SemanticIndex {
scan_complete.await;
let db_id = db.find_or_create_worktree(worktree_abs_path).await?;
let mut file_mtimes = db.get_file_mtimes(db_id).await?;
let worktree = if let Some(project) = project.upgrade(&cx) {
let worktree = if let Some(project) = project.upgrade() {
project
.read_with(&cx, |project, cx| project.worktree_for_id(worktree_id, cx))
.ok_or_else(|| anyhow!("worktree not found"))?
.ok()
.flatten()
.context("worktree not found")?
} else {
return anyhow::Ok(());
};
let worktree = worktree.read_with(&cx, |worktree, _| worktree.snapshot());
let worktree = worktree.read_with(&cx, |worktree, _| worktree.snapshot())?;
let mut changed_paths = cx
.background()
.background_executor()
.spawn(async move {
let mut changed_paths = BTreeMap::new();
for file in worktree.files(false, 0) {
@ -607,10 +617,8 @@ impl SemanticIndex {
let project_state = this
.projects
.get_mut(&project)
.ok_or_else(|| anyhow!("project not registered"))?;
let project = project
.upgrade(cx)
.ok_or_else(|| anyhow!("project was dropped"))?;
.context("project not registered")?;
let project = project.upgrade().context("project was dropped")?;
if let Some(WorktreeState::Registering(state)) =
project_state.worktrees.remove(&worktree_id)
@ -627,7 +635,7 @@ impl SemanticIndex {
this.index_project(project, cx).detach_and_log_err(cx);
anyhow::Ok(())
})?;
})??;
anyhow::Ok(())
};
@ -639,6 +647,7 @@ impl SemanticIndex {
project_state.worktrees.remove(&worktree_id);
});
})
.ok();
}
*done_tx.borrow_mut() = Some(());
@ -654,11 +663,7 @@ impl SemanticIndex {
);
}
fn project_worktrees_changed(
&mut self,
project: ModelHandle<Project>,
cx: &mut ModelContext<Self>,
) {
fn project_worktrees_changed(&mut self, project: Model<Project>, cx: &mut ModelContext<Self>) {
let project_state = if let Some(project_state) = self.projects.get_mut(&project.downgrade())
{
project_state
@ -668,7 +673,7 @@ impl SemanticIndex {
let mut worktrees = project
.read(cx)
.worktrees(cx)
.worktrees()
.filter(|worktree| worktree.read(cx).is_local())
.collect::<Vec<_>>();
let worktree_ids = worktrees
@ -691,10 +696,7 @@ impl SemanticIndex {
}
}
pub fn pending_file_count(
&self,
project: &ModelHandle<Project>,
) -> Option<watch::Receiver<usize>> {
pub fn pending_file_count(&self, project: &Model<Project>) -> Option<watch::Receiver<usize>> {
Some(
self.projects
.get(&project.downgrade())?
@ -705,7 +707,7 @@ impl SemanticIndex {
pub fn search_project(
&mut self,
project: ModelHandle<Project>,
project: Model<Project>,
query: String,
limit: usize,
includes: Vec<PathMatcher>,
@ -727,7 +729,7 @@ impl SemanticIndex {
.embed_batch(vec![query])
.await?
.pop()
.ok_or_else(|| anyhow!("could not embed query"))?;
.context("could not embed query")?;
log::trace!("Embedding Search Query: {:?}ms", t0.elapsed().as_millis());
let search_start = Instant::now();
@ -740,10 +742,10 @@ impl SemanticIndex {
&excludes,
cx,
)
});
})?;
let file_results = this.update(&mut cx, |this, cx| {
this.search_files(project, query, limit, includes, excludes, cx)
});
})?;
let (modified_buffer_results, file_results) =
futures::join!(modified_buffer_results, file_results);
@ -768,7 +770,7 @@ impl SemanticIndex {
pub fn search_files(
&mut self,
project: ModelHandle<Project>,
project: Model<Project>,
query: Embedding,
limit: usize,
includes: Vec<PathMatcher>,
@ -778,14 +780,18 @@ impl SemanticIndex {
let db_path = self.db.path().clone();
let fs = self.fs.clone();
cx.spawn(|this, mut cx| async move {
let database =
VectorDatabase::new(fs.clone(), db_path.clone(), cx.background()).await?;
let database = VectorDatabase::new(
fs.clone(),
db_path.clone(),
cx.background_executor().clone(),
)
.await?;
let worktree_db_ids = this.read_with(&cx, |this, _| {
let project_state = this
.projects
.get(&project.downgrade())
.ok_or_else(|| anyhow!("project was not indexed"))?;
.context("project was not indexed")?;
let worktree_db_ids = project_state
.worktrees
.values()
@ -798,13 +804,13 @@ impl SemanticIndex {
})
.collect::<Vec<i64>>();
anyhow::Ok(worktree_db_ids)
})?;
})??;
let file_ids = database
.retrieve_included_file_ids(&worktree_db_ids, &includes, &excludes)
.await?;
let batch_n = cx.background().num_cpus();
let batch_n = cx.background_executor().num_cpus();
let ids_len = file_ids.clone().len();
let minimum_batch_size = 50;
@ -824,9 +830,10 @@ impl SemanticIndex {
let fs = fs.clone();
let db_path = db_path.clone();
let query = query.clone();
if let Some(db) = VectorDatabase::new(fs, db_path.clone(), cx.background())
.await
.log_err()
if let Some(db) =
VectorDatabase::new(fs, db_path.clone(), cx.background_executor().clone())
.await
.log_err()
{
batch_results.push(async move {
db.top_k_search(&query, limit, batch.as_slice()).await
@ -864,6 +871,7 @@ impl SemanticIndex {
let mut ranges = Vec::new();
let weak_project = project.downgrade();
project.update(&mut cx, |project, cx| {
let this = this.upgrade().context("index was dropped")?;
for (worktree_db_id, file_path, byte_range) in spans {
let project_state =
if let Some(state) = this.read(cx).projects.get(&weak_project) {
@ -878,7 +886,7 @@ impl SemanticIndex {
}
Ok(())
})?;
})??;
let buffers = futures::future::join_all(tasks).await;
Ok(buffers
@ -887,11 +895,13 @@ impl SemanticIndex {
.zip(scores)
.filter_map(|((buffer, range), similarity)| {
let buffer = buffer.log_err()?;
let range = buffer.read_with(&cx, |buffer, _| {
let start = buffer.clip_offset(range.start, Bias::Left);
let end = buffer.clip_offset(range.end, Bias::Right);
buffer.anchor_before(start)..buffer.anchor_after(end)
});
let range = buffer
.read_with(&cx, |buffer, _| {
let start = buffer.clip_offset(range.start, Bias::Left);
let end = buffer.clip_offset(range.end, Bias::Right);
buffer.anchor_before(start)..buffer.anchor_after(end)
})
.log_err()?;
Some(SearchResult {
buffer,
range,
@ -904,7 +914,7 @@ impl SemanticIndex {
fn search_modified_buffers(
&self,
project: &ModelHandle<Project>,
project: &Model<Project>,
query: Embedding,
limit: usize,
includes: &[PathMatcher],
@ -913,7 +923,7 @@ impl SemanticIndex {
) -> Task<Result<Vec<SearchResult>>> {
let modified_buffers = project
.read(cx)
.opened_buffers(cx)
.opened_buffers()
.into_iter()
.filter_map(|buffer_handle| {
let buffer = buffer_handle.read(cx);
@ -941,8 +951,8 @@ impl SemanticIndex {
let embedding_provider = self.embedding_provider.clone();
let fs = self.fs.clone();
let db_path = self.db.path().clone();
let background = cx.background().clone();
cx.background().spawn(async move {
let background = cx.background_executor().clone();
cx.background_executor().spawn(async move {
let db = VectorDatabase::new(fs, db_path.clone(), background).await?;
let mut results = Vec::<SearchResult>::new();
@ -996,7 +1006,7 @@ impl SemanticIndex {
pub fn index_project(
&mut self,
project: ModelHandle<Project>,
project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if !self.is_authenticated() {
@ -1038,7 +1048,7 @@ impl SemanticIndex {
let project_state = this
.projects
.get_mut(&project.downgrade())
.ok_or_else(|| anyhow!("project was dropped"))?;
.context("project was dropped")?;
let pending_file_count_tx = &project_state.pending_file_count_tx;
project_state
@ -1080,9 +1090,9 @@ impl SemanticIndex {
});
anyhow::Ok(())
})?;
})??;
cx.background()
cx.background_executor()
.spawn(async move {
for (worktree_db_id, path) in files_to_delete {
db.delete_file(worktree_db_id, path).await.log_err();
@ -1138,11 +1148,11 @@ impl SemanticIndex {
let project_state = this
.projects
.get_mut(&project.downgrade())
.ok_or_else(|| anyhow!("project was dropped"))?;
.context("project was dropped")?;
project_state.pending_index -= 1;
cx.notify();
anyhow::Ok(())
})?;
})??;
Ok(())
})
@ -1150,15 +1160,15 @@ impl SemanticIndex {
fn wait_for_worktree_registration(
&self,
project: &ModelHandle<Project>,
project: &Model<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
let project = project.downgrade();
cx.spawn_weak(|this, cx| async move {
cx.spawn(|this, cx| async move {
loop {
let mut pending_worktrees = Vec::new();
this.upgrade(&cx)
.ok_or_else(|| anyhow!("semantic index dropped"))?
this.upgrade()
.context("semantic index dropped")?
.read_with(&cx, |this, _| {
if let Some(project) = this.projects.get(&project) {
for worktree in project.worktrees.values() {
@ -1167,7 +1177,7 @@ impl SemanticIndex {
}
}
}
});
})?;
if pending_worktrees.is_empty() {
break;
@ -1230,17 +1240,13 @@ impl SemanticIndex {
} else {
embeddings.next()
};
let embedding = embedding.ok_or_else(|| anyhow!("failed to embed spans"))?;
let embedding = embedding.context("failed to embed spans")?;
span.embedding = Some(embedding);
}
Ok(())
}
}
impl Entity for SemanticIndex {
type Event = ();
}
impl Drop for JobHandle {
fn drop(&mut self) {
if let Some(inner) = Arc::get_mut(&mut self.tx) {

View file

@ -1,7 +1,7 @@
use anyhow;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::Setting;
use settings::Settings;
#[derive(Deserialize, Debug)]
pub struct SemanticIndexSettings {
@ -13,7 +13,7 @@ pub struct SemanticIndexSettingsContent {
pub enabled: Option<bool>,
}
impl Setting for SemanticIndexSettings {
impl Settings for SemanticIndexSettings {
const KEY: Option<&'static str> = Some("semantic_index");
type FileContent = SemanticIndexSettingsContent;
@ -21,7 +21,7 @@ impl Setting for SemanticIndexSettings {
fn load(
default_value: &Self::FileContent,
user_values: &[&Self::FileContent],
_: &gpui::AppContext,
_: &mut gpui::AppContext,
) -> anyhow::Result<Self> {
Self::load_via_json_merge(default_value, user_values)
}

View file

@ -6,14 +6,14 @@ use crate::{
};
use ai::test::FakeEmbeddingProvider;
use gpui::{executor::Deterministic, Task, TestAppContext};
use gpui::{Task, TestAppContext};
use language::{Language, LanguageConfig, LanguageRegistry, ToOffset};
use parking_lot::Mutex;
use pretty_assertions::assert_eq;
use project::{project_settings::ProjectSettings, FakeFs, Fs, Project};
use rand::{rngs::StdRng, Rng};
use serde_json::json;
use settings::SettingsStore;
use settings::{Settings, SettingsStore};
use std::{path::Path, sync::Arc, time::SystemTime};
use unindent::Unindent;
use util::{paths::PathMatcher, RandomCharIter};
@ -26,10 +26,10 @@ fn init_logger() {
}
#[gpui::test]
async fn test_semantic_index(deterministic: Arc<Deterministic>, cx: &mut TestAppContext) {
async fn test_semantic_index(cx: &mut TestAppContext) {
init_test(cx);
let fs = FakeFs::new(cx.background());
let fs = FakeFs::new(cx.background_executor.clone());
fs.insert_tree(
"/the-root",
json!({
@ -91,9 +91,10 @@ async fn test_semantic_index(deterministic: Arc<Deterministic>, cx: &mut TestApp
});
let pending_file_count =
semantic_index.read_with(cx, |index, _| index.pending_file_count(&project).unwrap());
deterministic.run_until_parked();
cx.background_executor.run_until_parked();
assert_eq!(*pending_file_count.borrow(), 3);
deterministic.advance_clock(EMBEDDING_QUEUE_FLUSH_TIMEOUT);
cx.background_executor
.advance_clock(EMBEDDING_QUEUE_FLUSH_TIMEOUT);
assert_eq!(*pending_file_count.borrow(), 0);
let search_results = search_results.await.unwrap();
@ -170,13 +171,15 @@ async fn test_semantic_index(deterministic: Arc<Deterministic>, cx: &mut TestApp
.await
.unwrap();
deterministic.advance_clock(EMBEDDING_QUEUE_FLUSH_TIMEOUT);
cx.background_executor
.advance_clock(EMBEDDING_QUEUE_FLUSH_TIMEOUT);
let prev_embedding_count = embedding_provider.embedding_count();
let index = semantic_index.update(cx, |store, cx| store.index_project(project.clone(), cx));
deterministic.run_until_parked();
cx.background_executor.run_until_parked();
assert_eq!(*pending_file_count.borrow(), 1);
deterministic.advance_clock(EMBEDDING_QUEUE_FLUSH_TIMEOUT);
cx.background_executor
.advance_clock(EMBEDDING_QUEUE_FLUSH_TIMEOUT);
assert_eq!(*pending_file_count.borrow(), 0);
index.await.unwrap();
@ -220,13 +223,13 @@ async fn test_embedding_batching(cx: &mut TestAppContext, mut rng: StdRng) {
let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut queue = EmbeddingQueue::new(embedding_provider.clone(), cx.background());
let mut queue = EmbeddingQueue::new(embedding_provider.clone(), cx.background_executor.clone());
for file in &files {
queue.push(file.clone());
}
queue.flush();
cx.foreground().run_until_parked();
cx.background_executor.run_until_parked();
let finished_files = queue.finished_files();
let mut embedded_files: Vec<_> = files
.iter()
@ -1686,8 +1689,9 @@ fn test_subtract_ranges() {
fn init_test(cx: &mut TestAppContext) {
cx.update(|cx| {
cx.set_global(SettingsStore::test(cx));
settings::register::<SemanticIndexSettings>(cx);
settings::register::<ProjectSettings>(cx);
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
SemanticIndexSettings::register(cx);
ProjectSettings::register(cx);
});
}