Eliminate GPUI View, ViewContext, and WindowContext types (#22632)

There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:

- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`

Not pictured here are the two other failed attempts. It's been quite a
month!

Tasks:

- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs

### issues post merge

- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue



Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
This commit is contained in:
Nathan Sobo 2025-01-25 20:02:45 -07:00 committed by GitHub
parent 21b4a0d50e
commit 6fca1d2b0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
648 changed files with 36248 additions and 28208 deletions

View file

@ -1,6 +1,6 @@
use client::Client;
use futures::channel::oneshot;
use gpui::App;
use gpui::Application;
use http_client::HttpClientWithUrl;
use language::language_settings::AllLanguageSettings;
use project::Project;
@ -16,7 +16,7 @@ fn main() {
use clock::FakeSystemClock;
App::new().run(|cx| {
Application::new().run(|cx| {
let store = SettingsStore::test(cx);
cx.set_global(store);
language::init(cx);

View file

@ -1,5 +1,5 @@
use crate::{Embedding, EmbeddingProvider, TextToEmbed};
use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Context as _, Result};
use client::{proto, Client};
use collections::HashMap;
use futures::{future::BoxFuture, FutureExt};

View file

@ -10,7 +10,7 @@ use fs::Fs;
use fs::MTime;
use futures::{stream::StreamExt, FutureExt as _};
use futures_batch::ChunksTimeoutStreamExt;
use gpui::{AppContext, Model, Task};
use gpui::{App, Entity, Task};
use heed::types::{SerdeBincode, Str};
use language::LanguageRegistry;
use log;
@ -22,7 +22,7 @@ use util::ResultExt;
use worktree::Snapshot;
pub struct EmbeddingIndex {
worktree: Model<Worktree>,
worktree: Entity<Worktree>,
db_connection: heed::Env,
db: heed::Database<Str, SerdeBincode<EmbeddedFile>>,
fs: Arc<dyn Fs>,
@ -33,7 +33,7 @@ pub struct EmbeddingIndex {
impl EmbeddingIndex {
pub fn new(
worktree: Model<Worktree>,
worktree: Entity<Worktree>,
fs: Arc<dyn Fs>,
db_connection: heed::Env,
embedding_db: heed::Database<Str, SerdeBincode<EmbeddedFile>>,
@ -56,10 +56,7 @@ impl EmbeddingIndex {
&self.db
}
pub fn index_entries_changed_on_disk(
&self,
cx: &AppContext,
) -> impl Future<Output = Result<()>> {
pub fn index_entries_changed_on_disk(&self, cx: &App) -> impl Future<Output = Result<()>> {
if !cx.is_staff() {
return async move { Ok(()) }.boxed();
}
@ -80,7 +77,7 @@ impl EmbeddingIndex {
pub fn index_updated_entries(
&self,
updated_entries: UpdatedEntriesSet,
cx: &AppContext,
cx: &App,
) -> impl Future<Output = Result<()>> {
if !cx.is_staff() {
return async move { Ok(()) }.boxed();
@ -99,7 +96,7 @@ impl EmbeddingIndex {
.boxed()
}
fn scan_entries(&self, worktree: Snapshot, cx: &AppContext) -> ScanEntries {
fn scan_entries(&self, worktree: Snapshot, cx: &App) -> ScanEntries {
let (updated_entries_tx, updated_entries_rx) = channel::bounded(512);
let (deleted_entry_ranges_tx, deleted_entry_ranges_rx) = channel::bounded(128);
let db_connection = self.db_connection.clone();
@ -183,7 +180,7 @@ impl EmbeddingIndex {
&self,
worktree: Snapshot,
updated_entries: UpdatedEntriesSet,
cx: &AppContext,
cx: &App,
) -> ScanEntries {
let (updated_entries_tx, updated_entries_rx) = channel::bounded(512);
let (deleted_entry_ranges_tx, deleted_entry_ranges_rx) = channel::bounded(128);
@ -227,7 +224,7 @@ impl EmbeddingIndex {
&self,
worktree_abs_path: Arc<Path>,
entries: channel::Receiver<(Entry, IndexingEntryHandle)>,
cx: &AppContext,
cx: &App,
) -> ChunkFiles {
let language_registry = self.language_registry.clone();
let fs = self.fs.clone();
@ -277,7 +274,7 @@ impl EmbeddingIndex {
pub fn embed_files(
embedding_provider: Arc<dyn EmbeddingProvider>,
chunked_files: channel::Receiver<ChunkedFile>,
cx: &AppContext,
cx: &App,
) -> EmbedFiles {
let embedding_provider = embedding_provider.clone();
let (embedded_files_tx, embedded_files_rx) = channel::bounded(512);
@ -359,7 +356,7 @@ impl EmbeddingIndex {
&self,
deleted_entry_ranges: channel::Receiver<(Bound<String>, Bound<String>)>,
embedded_files: channel::Receiver<(EmbeddedFile, IndexingEntryHandle)>,
cx: &AppContext,
cx: &App,
) -> Task<Result<()>> {
let db_connection = self.db_connection.clone();
let db = self.db;
@ -397,7 +394,7 @@ impl EmbeddingIndex {
})
}
pub fn paths(&self, cx: &AppContext) -> Task<Result<Vec<Arc<Path>>>> {
pub fn paths(&self, cx: &App) -> Task<Result<Vec<Arc<Path>>>> {
let connection = self.db_connection.clone();
let db = self.db;
cx.background_executor().spawn(async move {
@ -413,11 +410,7 @@ impl EmbeddingIndex {
})
}
pub fn chunks_for_path(
&self,
path: Arc<Path>,
cx: &AppContext,
) -> Task<Result<Vec<EmbeddedChunk>>> {
pub fn chunks_for_path(&self, path: Arc<Path>, cx: &App) -> Task<Result<Vec<EmbeddedChunk>>> {
let connection = self.db_connection.clone();
let db = self.db;
cx.background_executor().spawn(async move {

View file

@ -3,13 +3,11 @@ use crate::{
summary_index::FileSummary,
worktree_index::{WorktreeIndex, WorktreeIndexHandle},
};
use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
use fs::Fs;
use futures::FutureExt;
use gpui::{
AppContext, Entity, EntityId, EventEmitter, Model, ModelContext, Subscription, Task, WeakModel,
};
use gpui::{App, Context, Entity, EntityId, EventEmitter, Subscription, Task, WeakEntity};
use language::LanguageRegistry;
use log;
use project::{Project, Worktree, WorktreeId};
@ -27,7 +25,7 @@ use util::ResultExt;
#[derive(Debug)]
pub struct SearchResult {
pub worktree: Model<Worktree>,
pub worktree: Entity<Worktree>,
pub path: Arc<Path>,
pub range: Range<usize>,
pub score: f32,
@ -60,7 +58,7 @@ pub enum Status {
pub struct ProjectIndex {
db_connection: heed::Env,
project: WeakModel<Project>,
project: WeakEntity<Project>,
worktree_indices: HashMap<EntityId, WorktreeIndexHandle>,
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
@ -73,10 +71,10 @@ pub struct ProjectIndex {
impl ProjectIndex {
pub fn new(
project: Model<Project>,
project: Entity<Project>,
db_connection: heed::Env,
embedding_provider: Arc<dyn EmbeddingProvider>,
cx: &mut ModelContext<Self>,
cx: &mut Context<Self>,
) -> Self {
let language_registry = project.read(cx).languages().clone();
let fs = project.read(cx).fs().clone();
@ -110,7 +108,7 @@ impl ProjectIndex {
self.last_status
}
pub fn project(&self) -> WeakModel<Project> {
pub fn project(&self) -> WeakEntity<Project> {
self.project.clone()
}
@ -120,9 +118,9 @@ impl ProjectIndex {
fn handle_project_event(
&mut self,
_: Model<Project>,
_: Entity<Project>,
event: &project::Event,
cx: &mut ModelContext<Self>,
cx: &mut Context<Self>,
) {
match event {
project::Event::WorktreeAdded(_) | project::Event::WorktreeRemoved(_) => {
@ -132,7 +130,7 @@ impl ProjectIndex {
}
}
fn update_worktree_indices(&mut self, cx: &mut ModelContext<Self>) {
fn update_worktree_indices(&mut self, cx: &mut Context<Self>) {
let Some(project) = self.project.upgrade() else {
return;
};
@ -198,7 +196,7 @@ impl ProjectIndex {
self.update_status(cx);
}
fn update_status(&mut self, cx: &mut ModelContext<Self>) {
fn update_status(&mut self, cx: &mut Context<Self>) {
let mut indexing_count = 0;
let mut any_loading = false;
@ -232,7 +230,7 @@ impl ProjectIndex {
&self,
queries: Vec<String>,
limit: usize,
cx: &AppContext,
cx: &App,
) -> Task<Result<Vec<SearchResult>>> {
let (chunks_tx, chunks_rx) = channel::bounded(1024);
let mut worktree_scan_tasks = Vec::new();
@ -372,7 +370,7 @@ impl ProjectIndex {
}
#[cfg(test)]
pub fn path_count(&self, cx: &AppContext) -> Result<u64> {
pub fn path_count(&self, cx: &App) -> Result<u64> {
let mut result = 0;
for worktree_index in self.worktree_indices.values() {
if let WorktreeIndexHandle::Loaded { index, .. } = worktree_index {
@ -385,8 +383,8 @@ impl ProjectIndex {
pub(crate) fn worktree_index(
&self,
worktree_id: WorktreeId,
cx: &AppContext,
) -> Option<Model<WorktreeIndex>> {
cx: &App,
) -> Option<Entity<WorktreeIndex>> {
for index in self.worktree_indices.values() {
if let WorktreeIndexHandle::Loaded { index, .. } = index {
if index.read(cx).worktree().read(cx).id() == worktree_id {
@ -397,7 +395,7 @@ impl ProjectIndex {
None
}
pub(crate) fn worktree_indices(&self, cx: &AppContext) -> Vec<Model<WorktreeIndex>> {
pub(crate) fn worktree_indices(&self, cx: &App) -> Vec<Entity<WorktreeIndex>> {
let mut result = self
.worktree_indices
.values()
@ -413,7 +411,7 @@ impl ProjectIndex {
result
}
pub fn all_summaries(&self, cx: &AppContext) -> Task<Result<Vec<FileSummary>>> {
pub fn all_summaries(&self, cx: &App) -> Task<Result<Vec<FileSummary>>> {
let (summaries_tx, summaries_rx) = channel::bounded(1024);
let mut worktree_scan_tasks = Vec::new();
for worktree_index in self.worktree_indices.values() {
@ -503,7 +501,7 @@ impl ProjectIndex {
}
/// Empty out the backlogs of all the worktrees in the project
pub fn flush_summary_backlogs(&self, cx: &AppContext) -> impl Future<Output = ()> {
pub fn flush_summary_backlogs(&self, cx: &App) -> impl Future<Output = ()> {
let flush_start = std::time::Instant::now();
futures::future::join_all(self.worktree_indices.values().map(|worktree_index| {
@ -540,7 +538,7 @@ impl ProjectIndex {
})
}
pub fn remaining_summaries(&self, cx: &mut ModelContext<Self>) -> usize {
pub fn remaining_summaries(&self, cx: &mut Context<Self>) -> usize {
self.worktree_indices(cx)
.iter()
.map(|index| index.read(cx).summary_index().backlog_len())

View file

@ -1,8 +1,8 @@
use crate::ProjectIndex;
use gpui::{
canvas, div, list, uniform_list, AnyElement, AppContext, CursorStyle, EventEmitter,
FocusHandle, FocusableView, IntoElement, ListOffset, ListState, Model, MouseMoveEvent, Render,
UniformListScrollHandle, View,
canvas, div, list, uniform_list, AnyElement, App, CursorStyle, Entity, EventEmitter,
FocusHandle, Focusable, IntoElement, ListOffset, ListState, MouseMoveEvent, Render,
UniformListScrollHandle,
};
use project::WorktreeId;
use settings::Settings;
@ -12,7 +12,7 @@ use ui::prelude::*;
use workspace::item::Item;
pub struct ProjectIndexDebugView {
index: Model<ProjectIndex>,
index: Entity<ProjectIndex>,
rows: Vec<Row>,
selected_path: Option<PathState>,
hovered_row_ix: Option<usize>,
@ -33,23 +33,25 @@ enum Row {
}
impl ProjectIndexDebugView {
pub fn new(index: Model<ProjectIndex>, cx: &mut ViewContext<Self>) -> Self {
pub fn new(index: Entity<ProjectIndex>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let mut this = Self {
rows: Vec::new(),
list_scroll_handle: UniformListScrollHandle::new(),
selected_path: None,
hovered_row_ix: None,
focus_handle: cx.focus_handle(),
_subscription: cx.subscribe(&index, |this, _, _, cx| this.update_rows(cx)),
_subscription: cx.subscribe_in(&index, window, |this, _, _, window, cx| {
this.update_rows(window, cx)
}),
index,
};
this.update_rows(cx);
this.update_rows(window, cx);
this
}
fn update_rows(&mut self, cx: &mut ViewContext<Self>) {
fn update_rows(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let worktree_indices = self.index.read(cx).worktree_indices(cx);
cx.spawn(|this, mut cx| async move {
cx.spawn_in(window, |this, mut cx| async move {
let mut rows = Vec::new();
for index in worktree_indices {
@ -83,7 +85,8 @@ impl ProjectIndexDebugView {
&mut self,
worktree_id: WorktreeId,
file_path: Arc<Path>,
cx: &mut ViewContext<Self>,
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<()> {
let project_index = self.index.read(cx);
let fs = project_index.fs().clone();
@ -93,7 +96,7 @@ impl ProjectIndexDebugView {
.embedding_index()
.chunks_for_path(file_path.clone(), cx);
cx.spawn(|this, mut cx| async move {
cx.spawn_in(window, |this, mut cx| async move {
let chunks = chunks.await?;
let content = fs.load(&root_path.join(&file_path)).await?;
let chunks = chunks
@ -112,14 +115,14 @@ impl ProjectIndexDebugView {
.collect::<Vec<_>>();
this.update(&mut cx, |this, cx| {
let view = cx.view().downgrade();
let view = cx.model().downgrade();
this.selected_path = Some(PathState {
path: file_path,
list_state: ListState::new(
chunks.len(),
gpui::ListAlignment::Top,
px(100.),
move |ix, cx| {
move |ix, _, cx| {
if let Some(view) = view.upgrade() {
view.update(cx, |view, cx| view.render_chunk(ix, cx))
} else {
@ -136,7 +139,7 @@ impl ProjectIndexDebugView {
None
}
fn render_chunk(&mut self, ix: usize, cx: &mut ViewContext<Self>) -> AnyElement {
fn render_chunk(&mut self, ix: usize, cx: &mut Context<Self>) -> AnyElement {
let buffer_font = ThemeSettings::get_global(cx).buffer_font.clone();
let Some(state) = &self.selected_path else {
return div().into_any();
@ -163,16 +166,16 @@ impl ProjectIndexDebugView {
.child(
Button::new(("prev", ix), "prev")
.disabled(ix == 0)
.on_click(cx.listener(move |this, _, _| {
.on_click(cx.listener(move |this, _, _, _| {
this.scroll_to_chunk(ix.saturating_sub(1))
})),
)
.child(
Button::new(("next", ix), "next")
.disabled(ix + 1 == state.chunks.len())
.on_click(
cx.listener(move |this, _, _| this.scroll_to_chunk(ix + 1)),
),
.on_click(cx.listener(move |this, _, _, _| {
this.scroll_to_chunk(ix + 1)
})),
),
),
)
@ -196,7 +199,7 @@ impl ProjectIndexDebugView {
}
impl Render for ProjectIndexDebugView {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if let Some(selected_path) = self.selected_path.as_ref() {
v_flex()
.child(
@ -211,7 +214,7 @@ impl Render for ProjectIndexDebugView {
.border_b_1()
.border_color(cx.theme().colors().border)
.cursor(CursorStyle::PointingHand)
.on_click(cx.listener(|this, _, cx| {
.on_click(cx.listener(|this, _, _, cx| {
this.selected_path.take();
cx.notify();
})),
@ -221,10 +224,10 @@ impl Render for ProjectIndexDebugView {
.into_any_element()
} else {
let mut list = uniform_list(
cx.view().clone(),
cx.model().clone(),
"ProjectIndexDebugView",
self.rows.len(),
move |this, range, cx| {
move |this, range, _, cx| {
this.rows[range]
.iter()
.enumerate()
@ -236,18 +239,25 @@ impl Render for ProjectIndexDebugView {
.id(ix)
.pl_8()
.child(Label::new(file_path.to_string_lossy().to_string()))
.on_mouse_move(cx.listener(move |this, _: &MouseMoveEvent, cx| {
if this.hovered_row_ix != Some(ix) {
this.hovered_row_ix = Some(ix);
cx.notify();
}
}))
.on_mouse_move(cx.listener(
move |this, _: &MouseMoveEvent, _, cx| {
if this.hovered_row_ix != Some(ix) {
this.hovered_row_ix = Some(ix);
cx.notify();
}
},
))
.cursor(CursorStyle::PointingHand)
.on_click(cx.listener({
let worktree_id = *worktree_id;
let file_path = file_path.clone();
move |this, _, cx| {
this.handle_path_click(worktree_id, file_path.clone(), cx);
move |this, _, window, cx| {
this.handle_path_click(
worktree_id,
file_path.clone(),
window,
cx,
);
}
})),
})
@ -260,12 +270,12 @@ impl Render for ProjectIndexDebugView {
.into_any_element();
canvas(
move |bounds, cx| {
list.prepaint_as_root(bounds.origin, bounds.size.into(), cx);
move |bounds, window, cx| {
list.prepaint_as_root(bounds.origin, bounds.size.into(), window, cx);
list
},
|_, mut list, cx| {
list.paint(cx);
|_, mut list, window, cx| {
list.paint(window, cx);
},
)
.size_full()
@ -279,24 +289,25 @@ impl EventEmitter<()> for ProjectIndexDebugView {}
impl Item for ProjectIndexDebugView {
type Event = ();
fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
Some("Project Index (Debug)".into())
}
fn clone_on_split(
&self,
_: Option<workspace::WorkspaceId>,
cx: &mut ViewContext<Self>,
) -> Option<View<Self>>
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Entity<Self>>
where
Self: Sized,
{
Some(cx.new_view(|cx| Self::new(self.index.clone(), cx)))
Some(cx.new(|cx| Self::new(self.index.clone(), window, cx)))
}
}
impl FocusableView for ProjectIndexDebugView {
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
impl Focusable for ProjectIndexDebugView {
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}

View file

@ -11,7 +11,9 @@ mod worktree_index;
use anyhow::{Context as _, Result};
use collections::HashMap;
use fs::Fs;
use gpui::{AppContext, AsyncAppContext, BorrowAppContext, Context, Global, Model, WeakModel};
use gpui::{
App, AppContext as _, AsyncAppContext, BorrowAppContext, Context, Entity, Global, WeakEntity,
};
use language::LineEnding;
use project::{Project, Worktree};
use std::{
@ -19,7 +21,6 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
use ui::ViewContext;
use util::ResultExt as _;
use workspace::Workspace;
@ -31,7 +32,7 @@ pub use summary_index::FileSummary;
pub struct SemanticDb {
embedding_provider: Arc<dyn EmbeddingProvider>,
db_connection: Option<heed::Env>,
project_indices: HashMap<WeakModel<Project>, Model<ProjectIndex>>,
project_indices: HashMap<WeakEntity<Project>, Entity<ProjectIndex>>,
}
impl Global for SemanticDb {}
@ -57,8 +58,8 @@ impl SemanticDb {
.context("opening database connection")?;
cx.update(|cx| {
cx.observe_new_views(
|workspace: &mut Workspace, cx: &mut ViewContext<Workspace>| {
cx.observe_new(
|workspace: &mut Workspace, _window, cx: &mut Context<Workspace>| {
let project = workspace.project().clone();
if cx.has_global::<SemanticDb>() {
@ -108,7 +109,7 @@ impl SemanticDb {
.then_with(|| a.range.start.cmp(&b.range.start))
});
let mut last_loaded_file: Option<(Model<Worktree>, Arc<Path>, PathBuf, String)> = None;
let mut last_loaded_file: Option<(Entity<Worktree>, Arc<Path>, PathBuf, String)> = None;
let mut loaded_results = Vec::<LoadedSearchResult>::new();
for result in results {
let full_path;
@ -208,16 +209,16 @@ impl SemanticDb {
pub fn project_index(
&mut self,
project: Model<Project>,
_cx: &mut AppContext,
) -> Option<Model<ProjectIndex>> {
project: Entity<Project>,
_cx: &mut App,
) -> Option<Entity<ProjectIndex>> {
self.project_indices.get(&project.downgrade()).cloned()
}
pub fn remaining_summaries(
&self,
project: &WeakModel<Project>,
cx: &mut AppContext,
project: &WeakEntity<Project>,
cx: &mut App,
) -> Option<usize> {
self.project_indices.get(project).map(|project_index| {
project_index.update(cx, |project_index, cx| {
@ -228,10 +229,10 @@ impl SemanticDb {
pub fn create_project_index(
&mut self,
project: Model<Project>,
cx: &mut AppContext,
) -> Model<ProjectIndex> {
let project_index = cx.new_model(|cx| {
project: Entity<Project>,
cx: &mut App,
) -> Entity<ProjectIndex> {
let project_index = cx.new(|cx| {
ProjectIndex::new(
project.clone(),
self.db_connection.clone().unwrap(),

View file

@ -3,7 +3,7 @@ use arrayvec::ArrayString;
use fs::{Fs, MTime};
use futures::{stream::StreamExt, TryFutureExt};
use futures_batch::ChunksTimeoutStreamExt;
use gpui::{AppContext, Model, Task};
use gpui::{App, Entity, Task};
use heed::{
types::{SerdeBincode, Str},
RoTxn,
@ -79,7 +79,7 @@ struct SummarizeFiles {
}
pub struct SummaryIndex {
worktree: Model<Worktree>,
worktree: Entity<Worktree>,
fs: Arc<dyn Fs>,
db_connection: heed::Env,
file_digest_db: heed::Database<Str, SerdeBincode<FileDigest>>, // Key: file path. Val: BLAKE3 digest of its contents.
@ -100,7 +100,7 @@ struct MightNeedSummaryFiles {
impl SummaryIndex {
pub fn new(
worktree: Model<Worktree>,
worktree: Entity<Worktree>,
fs: Arc<dyn Fs>,
db_connection: heed::Env,
file_digest_db: heed::Database<Str, SerdeBincode<FileDigest>>,
@ -129,7 +129,7 @@ impl SummaryIndex {
pub fn index_entries_changed_on_disk(
&self,
is_auto_available: bool,
cx: &AppContext,
cx: &App,
) -> impl Future<Output = Result<()>> {
let start = Instant::now();
let backlogged;
@ -192,7 +192,7 @@ impl SummaryIndex {
&mut self,
updated_entries: UpdatedEntriesSet,
is_auto_available: bool,
cx: &AppContext,
cx: &App,
) -> impl Future<Output = Result<()>> {
let start = Instant::now();
let backlogged;
@ -249,7 +249,7 @@ impl SummaryIndex {
fn check_summary_cache(
&self,
might_need_summary: channel::Receiver<UnsummarizedFile>,
cx: &AppContext,
cx: &App,
) -> NeedsSummary {
let db_connection = self.db_connection.clone();
let db = self.summary_db;
@ -286,7 +286,7 @@ impl SummaryIndex {
}
}
fn scan_entries(&self, worktree: Snapshot, cx: &AppContext) -> Backlogged {
fn scan_entries(&self, worktree: Snapshot, cx: &App) -> Backlogged {
let (tx, rx) = channel::bounded(512);
let db_connection = self.db_connection.clone();
let digest_db = self.file_digest_db;
@ -360,7 +360,7 @@ impl SummaryIndex {
&self,
worktree: Snapshot,
updated_entries: UpdatedEntriesSet,
cx: &AppContext,
cx: &App,
) -> Backlogged {
log::info!("Scanning for updated entries that might need summarization...");
let (tx, rx) = channel::bounded(512);
@ -418,7 +418,7 @@ impl SummaryIndex {
&self,
paths: channel::Receiver<Vec<(Arc<Path>, Option<MTime>)>>,
worktree_abs_path: Arc<Path>,
cx: &AppContext,
cx: &App,
) -> MightNeedSummaryFiles {
let fs = self.fs.clone();
let (rx, tx) = channel::bounded(2048);
@ -487,7 +487,7 @@ impl SummaryIndex {
fn summarize_files(
&self,
unsummarized_files: channel::Receiver<UnsummarizedFile>,
cx: &AppContext,
cx: &App,
) -> SummarizeFiles {
let (summarized_tx, summarized_rx) = channel::bounded(512);
let task = cx.spawn(|cx| async move {
@ -528,11 +528,7 @@ impl SummaryIndex {
}
}
fn summarize_code(
code: &str,
path: &Path,
cx: &AppContext,
) -> impl Future<Output = Result<String>> {
fn summarize_code(code: &str, path: &Path, cx: &App) -> impl Future<Output = Result<String>> {
let start = Instant::now();
let (summary_model_id, use_cache): (LanguageModelId, bool) = (
"Qwen/Qwen2-7B-Instruct".to_string().into(), // TODO read this from the user's settings.
@ -603,7 +599,7 @@ impl SummaryIndex {
fn persist_summaries(
&self,
summaries: channel::Receiver<SummarizedFile>,
cx: &AppContext,
cx: &App,
) -> Task<Result<()>> {
let db_connection = self.db_connection.clone();
let digest_db = self.file_digest_db;
@ -643,7 +639,7 @@ impl SummaryIndex {
pub(crate) fn flush_backlog(
&self,
worktree_abs_path: Arc<Path>,
cx: &AppContext,
cx: &App,
) -> impl Future<Output = Result<()>> {
let start = Instant::now();
let backlogged = {

View file

@ -7,7 +7,7 @@ use feature_flags::{AutoCommand, FeatureFlagAppExt};
use fs::Fs;
use futures::future::Shared;
use gpui::{
AppContext, AsyncAppContext, Context, Model, ModelContext, Subscription, Task, WeakModel,
App, AppContext as _, AsyncAppContext, Context, Entity, Subscription, Task, WeakEntity,
};
use language::LanguageRegistry;
use log;
@ -19,15 +19,15 @@ use util::ResultExt;
#[derive(Clone)]
pub enum WorktreeIndexHandle {
Loading {
index: Shared<Task<Result<Model<WorktreeIndex>, Arc<anyhow::Error>>>>,
index: Shared<Task<Result<Entity<WorktreeIndex>, Arc<anyhow::Error>>>>,
},
Loaded {
index: Model<WorktreeIndex>,
index: Entity<WorktreeIndex>,
},
}
pub struct WorktreeIndex {
worktree: Model<Worktree>,
worktree: Entity<Worktree>,
db_connection: heed::Env,
embedding_index: EmbeddingIndex,
summary_index: SummaryIndex,
@ -38,14 +38,14 @@ pub struct WorktreeIndex {
impl WorktreeIndex {
pub fn load(
worktree: Model<Worktree>,
worktree: Entity<Worktree>,
db_connection: heed::Env,
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
status_tx: channel::Sender<()>,
embedding_provider: Arc<dyn EmbeddingProvider>,
cx: &mut AppContext,
) -> Task<Result<Model<Self>>> {
cx: &mut App,
) -> Task<Result<Entity<Self>>> {
let worktree_for_index = worktree.clone();
let worktree_for_summary = worktree.clone();
let worktree_abs_path = worktree.read(cx).abs_path();
@ -106,7 +106,7 @@ impl WorktreeIndex {
})
.await?;
cx.new_model(|cx| {
cx.new(|cx| {
Self::new(
worktree,
db_connection,
@ -121,12 +121,12 @@ impl WorktreeIndex {
#[allow(clippy::too_many_arguments)]
pub fn new(
worktree: Model<Worktree>,
worktree: Entity<Worktree>,
db_connection: heed::Env,
embedding_index: EmbeddingIndex,
summary_index: SummaryIndex,
entry_ids_being_indexed: Arc<IndexingEntrySet>,
cx: &mut ModelContext<Self>,
cx: &mut Context<Self>,
) -> Self {
let (updated_entries_tx, updated_entries_rx) = channel::unbounded();
let _subscription = cx.subscribe(&worktree, move |_this, _worktree, event, _cx| {
@ -151,7 +151,7 @@ impl WorktreeIndex {
self.entry_ids_being_indexed.as_ref()
}
pub fn worktree(&self) -> &Model<Worktree> {
pub fn worktree(&self) -> &Entity<Worktree> {
&self.worktree
}
@ -168,7 +168,7 @@ impl WorktreeIndex {
}
async fn index_entries(
this: WeakModel<Self>,
this: WeakEntity<Self>,
updated_entries: channel::Receiver<UpdatedEntriesSet>,
mut cx: AsyncAppContext,
) -> Result<()> {
@ -206,7 +206,7 @@ impl WorktreeIndex {
#[cfg(test)]
pub fn path_count(&self) -> Result<u64> {
use anyhow::Context;
use anyhow::Context as _;
let txn = self
.db_connection