Improve the ergonomics of creating local buffers (#10347)
This PR renames `language::Buffer::new` to `language::Buffer::local` and
simplifies its interface. Instead of taking a replica id (which should
always be 0 for the local case) and a `BufferId`, which was awkward and
verbose to construct, it simply takes text and a `cx`.
It uses the `cx` to derive a `BufferId` from the `EntityId` associated
with the `cx`, which should always be positive based on the following
analysis...
We convert the entity id to a u64 using this method on `EntityId`, which
is defined by macros in the `slotmap` crate:
```rust
pub fn as_ffi(self) -> u64 {
(u64::from(self.version.get()) << 32) | u64::from(self.idx)
}
```
If you look at the type of `version` in `KeyData`, it is non-zero:
```rust
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct KeyData {
idx: u32,
version: NonZeroU32,
}
```
This commit also adds `Context::reserve_model` and
`Context::insert_model` to determine a model's entity ID before it is
created, which we need in order to assign a `BufferId` in the background
when loading a buffer asynchronously.
Release Notes:
- N/A
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
co-authored by
Piotr Osiewicz
parent
664efef76b
commit
7abb63cfda
@@ -751,20 +751,21 @@ impl LocalWorktree {
|
||||
|
||||
pub fn load_buffer(
|
||||
&mut self,
|
||||
id: BufferId,
|
||||
path: &Path,
|
||||
cx: &mut ModelContext<Worktree>,
|
||||
) -> Task<Result<Model<Buffer>>> {
|
||||
let path = Arc::from(path);
|
||||
let reservation = cx.reserve_model();
|
||||
let buffer_id = BufferId::from(reservation.entity_id().as_non_zero_u64());
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
let (file, contents, diff_base) = this
|
||||
.update(&mut cx, |t, cx| t.as_local().unwrap().load(&path, cx))?
|
||||
.await?;
|
||||
let text_buffer = cx
|
||||
.background_executor()
|
||||
.spawn(async move { text::Buffer::new(0, id, contents) })
|
||||
.spawn(async move { text::Buffer::new(0, buffer_id, contents) })
|
||||
.await;
|
||||
cx.new_model(|_| {
|
||||
cx.insert_model(reservation, |_| {
|
||||
Buffer::build(
|
||||
text_buffer,
|
||||
diff_base,
|
||||
@@ -777,13 +778,13 @@ impl LocalWorktree {
|
||||
|
||||
pub fn new_buffer(
|
||||
&mut self,
|
||||
buffer_id: BufferId,
|
||||
path: Arc<Path>,
|
||||
cx: &mut ModelContext<Worktree>,
|
||||
) -> Model<Buffer> {
|
||||
let text_buffer = text::Buffer::new(0, buffer_id, "".into());
|
||||
let worktree = cx.handle();
|
||||
cx.new_model(|_| {
|
||||
cx.new_model(|cx| {
|
||||
let buffer_id = BufferId::from(cx.entity_id().as_non_zero_u64());
|
||||
let text_buffer = text::Buffer::new(0, buffer_id, "".into());
|
||||
Buffer::build(
|
||||
text_buffer,
|
||||
None,
|
||||
|
||||
@@ -21,7 +21,6 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
use text::BufferId;
|
||||
use util::{http::FakeHttpClient, test::temp_tree, ResultExt};
|
||||
|
||||
#[gpui::test]
|
||||
@@ -577,11 +576,9 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) {
|
||||
let prev_read_dir_count = fs.read_dir_call_count();
|
||||
let buffer = tree
|
||||
.update(cx, |tree, cx| {
|
||||
tree.as_local_mut().unwrap().load_buffer(
|
||||
BufferId::new(1).unwrap(),
|
||||
"one/node_modules/b/b1.js".as_ref(),
|
||||
cx,
|
||||
)
|
||||
tree.as_local_mut()
|
||||
.unwrap()
|
||||
.load_buffer("one/node_modules/b/b1.js".as_ref(), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -621,11 +618,9 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) {
|
||||
let prev_read_dir_count = fs.read_dir_call_count();
|
||||
let buffer = tree
|
||||
.update(cx, |tree, cx| {
|
||||
tree.as_local_mut().unwrap().load_buffer(
|
||||
BufferId::new(1).unwrap(),
|
||||
"one/node_modules/a/a2.js".as_ref(),
|
||||
cx,
|
||||
)
|
||||
tree.as_local_mut()
|
||||
.unwrap()
|
||||
.load_buffer("one/node_modules/a/a2.js".as_ref(), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user