Detailed changes
@@ -31,7 +31,7 @@ use gpui::{
StatefulInteractiveElement, Styled, Subscription, Task, TextStyle, UniformListScrollHandle,
View, ViewContext, VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext,
};
-use language::{language_settings::SoftWrap, Buffer, BufferId, LanguageRegistry, ToOffset as _};
+use language::{language_settings::SoftWrap, Buffer, LanguageRegistry, ToOffset as _};
use parking_lot::Mutex;
use project::Project;
use search::{buffer_search::DivRegistrar, BufferSearchBar};
@@ -1310,7 +1310,7 @@ impl Conversation {
) -> Self {
let markdown = language_registry.language_for_name("Markdown");
let buffer = cx.new_model(|cx| {
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "");
+ let mut buffer = Buffer::local("", cx);
buffer.set_language_registry(language_registry);
cx.spawn(|buffer, mut cx| async move {
let markdown = markdown.await?;
@@ -1398,11 +1398,7 @@ impl Conversation {
let mut message_anchors = Vec::new();
let mut next_message_id = MessageId(0);
let buffer = cx.new_model(|cx| {
- let mut buffer = Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- saved_conversation.text,
- );
+ let mut buffer = Buffer::local(saved_conversation.text, cx);
for message in saved_conversation.messages {
message_anchors.push(MessageAnchor {
id: message.id,
@@ -361,8 +361,8 @@ mod tests {
use gpui::{Context, TestAppContext};
use indoc::indoc;
use language::{
- language_settings, tree_sitter_rust, Buffer, BufferId, Language, LanguageConfig,
- LanguageMatcher, Point,
+ language_settings, tree_sitter_rust, Buffer, Language, LanguageConfig, LanguageMatcher,
+ Point,
};
use rand::prelude::*;
use serde::Serialize;
@@ -388,9 +388,8 @@ mod tests {
}
}
"};
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(1).unwrap(), text).with_language(Arc::new(rust_lang()), cx)
- });
+ let buffer =
+ cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let range = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
@@ -447,9 +446,8 @@ mod tests {
le
}
"};
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(1).unwrap(), text).with_language(Arc::new(rust_lang()), cx)
- });
+ let buffer =
+ cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let position = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
@@ -506,9 +504,8 @@ mod tests {
" \n",
"}\n" //
);
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(1).unwrap(), text).with_language(Arc::new(rust_lang()), cx)
- });
+ let buffer =
+ cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let position = buffer.read_with(cx, |buffer, cx| {
let snapshot = buffer.snapshot(cx);
@@ -1042,9 +1042,7 @@ mod tests {
async fn test_buffer_management(cx: &mut TestAppContext) {
let (copilot, mut lsp) = Copilot::fake(cx);
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "Hello")
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local("Hello", cx));
let buffer_1_uri: lsp::Url = format!("buffer://{}", buffer_1.entity_id().as_u64())
.parse()
.unwrap();
@@ -1062,13 +1060,7 @@ mod tests {
}
);
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "Goodbye",
- )
- });
+ let buffer_2 = cx.new_model(|cx| Buffer::local("Goodbye", cx));
let buffer_2_uri: lsp::Url = format!("buffer://{}", buffer_2.entity_id().as_u64())
.parse()
.unwrap();
@@ -272,7 +272,7 @@ mod tests {
use indoc::indoc;
use language::{
language_settings::{AllLanguageSettings, AllLanguageSettingsContent},
- BufferId, Point,
+ Point,
};
use project::Project;
use serde_json::json;
@@ -729,20 +729,8 @@ mod tests {
let (copilot, copilot_lsp) = Copilot::fake(cx);
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "a = 1\nb = 2\n",
- )
- });
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "c = 3\nd = 4\n",
- )
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local("a = 1\nb = 2\n", cx));
+ let buffer_2 = cx.new_model(|cx| Buffer::local("c = 3\nd = 4\n", cx));
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, language::Capability::ReadWrite);
multibuffer.push_excerpts(
@@ -984,7 +984,6 @@ pub mod tests {
use settings::SettingsStore;
use smol::stream::StreamExt;
use std::{env, sync::Arc};
- use text::BufferId;
use theme::{LoadThemes, SyntaxTheme};
use util::test::{marked_text_ranges, sample_text};
use Bias::*;
@@ -1445,10 +1444,7 @@ pub mod tests {
cx.update(|cx| init_test(cx, |s| s.defaults.tab_size = Some(2.try_into().unwrap())));
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
@@ -1533,10 +1529,7 @@ pub mod tests {
cx.update(|cx| init_test(cx, |_| {}));
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
@@ -1602,10 +1595,7 @@ pub mod tests {
let (text, highlighted_ranges) = marked_text_ranges(r#"constΛ Β«aΒ»: B = "c Β«dΒ»""#, false);
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
cx.condition(&buffer, |buf, _| !buf.is_parsing()).await;
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
@@ -1328,37 +1328,19 @@ impl InlayHintRefreshReason {
impl Editor {
pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- String::new(),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local("", cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::SingleLine, buffer, None, cx)
}
pub fn multi_line(cx: &mut ViewContext<Self>) -> Self {
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- String::new(),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local("", cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::Full, buffer, None, cx)
}
pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- String::new(),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local("", cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::AutoHeight { max_lines }, buffer, None, cx)
}
@@ -38,8 +38,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
init_test(cx, |_| {});
let buffer = cx.new_model(|cx| {
- let mut buffer =
- language::Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "123456");
+ let mut buffer = language::Buffer::local("123456", cx);
buffer.set_group_interval(Duration::from_secs(1));
buffer
});
@@ -154,9 +153,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
init_test(cx, |_| {});
let mut now = Instant::now();
- let buffer = cx.new_model(|cx| {
- language::Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "123456")
- });
+ let buffer = cx.new_model(|cx| language::Buffer::local("123456", cx));
let group_interval = buffer.update(cx, |buffer, _| buffer.transaction_group_interval());
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let editor = cx.add_window(|cx| build_editor(buffer.clone(), cx));
@@ -227,8 +224,7 @@ fn test_ime_composition(cx: &mut TestAppContext) {
init_test(cx, |_| {});
let buffer = cx.new_model(|cx| {
- let mut buffer =
- language::Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abcde");
+ let mut buffer = language::Buffer::local("abcde", cx);
// Ensure automatic grouping doesn't occur.
buffer.set_group_interval(Duration::ZERO);
buffer
@@ -2344,21 +2340,10 @@ fn test_indent_outdent_with_excerpts(cx: &mut TestAppContext) {
None,
));
- let toml_buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "a = 1\nb = 2\n",
- )
- .with_language(toml_language, cx)
- });
+ let toml_buffer =
+ cx.new_model(|cx| Buffer::local("a = 1\nb = 2\n", cx).with_language(toml_language, cx));
let rust_buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "const c: usize = 3;\n",
- )
- .with_language(rust_language, cx)
+ Buffer::local("const c: usize = 3;\n", cx).with_language(rust_language, cx)
});
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
@@ -4304,10 +4289,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
@@ -4471,10 +4453,7 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
let text = "fn a() {}";
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
editor
@@ -5129,10 +5108,7 @@ async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
view.condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
@@ -5280,10 +5256,7 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
editor
@@ -5470,10 +5443,7 @@ async fn test_auto_replace_emoji_shortcode(cx: &mut gpui::TestAppContext) {
Some(tree_sitter_rust::language()),
));
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "")
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local("", cx).with_language(language, cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
editor
@@ -6939,13 +6909,7 @@ async fn test_toggle_block_comment(cx: &mut gpui::TestAppContext) {
fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(3, 4, 'a'),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(sample_text(3, 4, 'a'), cx));
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
multibuffer.push_excerpts(
@@ -7029,13 +6993,7 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
primary: None,
}
});
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- initial_text,
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(initial_text, cx));
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
@@ -7093,13 +7051,7 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
fn test_refresh_selections(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(3, 4, 'a'),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(sample_text(3, 4, 'a'), cx));
let mut excerpt1_id = None;
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
@@ -7184,13 +7136,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
init_test(cx, |_| {});
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(3, 4, 'a'),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(sample_text(3, 4, 'a'), cx));
let mut excerpt1_id = None;
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
@@ -7285,10 +7231,7 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
"{{} }\n", //
);
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
let (view, cx) = cx.add_window_view(|cx| build_editor(buffer, cx));
view.condition::<crate::EditorEvent>(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
@@ -8989,31 +8932,13 @@ async fn test_multibuffer_reverts(cx: &mut gpui::TestAppContext) {
cx.executor().run_until_parked();
}
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text_1.clone(),
- )
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text_1.clone(), cx));
diff_every_buffer_row(&buffer_1, sample_text_1.clone(), cols, cx);
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(
- 1,
- BufferId::new(cx.entity_id().as_u64() + 1).unwrap(),
- sample_text_2.clone(),
- )
- });
+ let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text_2.clone(), cx));
diff_every_buffer_row(&buffer_2, sample_text_2.clone(), cols, cx);
- let buffer_3 = cx.new_model(|cx| {
- Buffer::new(
- 2,
- BufferId::new(cx.entity_id().as_u64() + 2).unwrap(),
- sample_text_3.clone(),
- )
- });
+ let buffer_3 = cx.new_model(|cx| Buffer::local(sample_text_3.clone(), cx));
diff_every_buffer_row(&buffer_3, sample_text_3.clone(), cols, cx);
let multibuffer = cx.new_model(|cx| {
@@ -9152,29 +9077,9 @@ async fn test_mutlibuffer_in_navigation_history(cx: &mut gpui::TestAppContext) {
"vvvv\nwwww\nxxxx\nyyyy\nzzzz\n{{{{\n||||\n}}}}\n~~~~\n\u{7f}\u{7f}\u{7f}\u{7f}"
);
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text_1.clone(),
- )
- });
-
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(
- 1,
- BufferId::new(cx.entity_id().as_u64() + 1).unwrap(),
- sample_text_2.clone(),
- )
- });
-
- let buffer_3 = cx.new_model(|cx| {
- Buffer::new(
- 2,
- BufferId::new(cx.entity_id().as_u64() + 2).unwrap(),
- sample_text_3.clone(),
- )
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text_1.clone(), cx));
+ let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text_2.clone(), cx));
+ let buffer_3 = cx.new_model(|cx| Buffer::local(sample_text_3.clone(), cx));
let multi_buffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
@@ -570,7 +570,6 @@ mod tests {
use language::Capability;
use project::Project;
use settings::SettingsStore;
- use text::BufferId;
use util::post_inc;
#[gpui::test]
@@ -870,13 +869,7 @@ mod tests {
let font = font("Helvetica");
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "abc\ndefg\nhijkl\nmn",
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local("abc\ndefg\nhijkl\nmn", cx));
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
multibuffer.push_excerpts(
@@ -21,7 +21,6 @@ use std::{
Arc,
},
};
-use text::BufferId;
use ui::Context;
use util::{
assert_set_eq,
@@ -76,10 +75,9 @@ impl EditorTestContext {
) -> EditorTestContext {
let mut multibuffer = MultiBuffer::new(0, language::Capability::ReadWrite);
let buffer = cx.new_model(|cx| {
- for (i, excerpt) in excerpts.into_iter().enumerate() {
+ for excerpt in excerpts.into_iter() {
let (text, ranges) = marked_text_ranges(excerpt, false);
- let buffer =
- cx.new_model(|_| Buffer::new(0, BufferId::new(i as u64 + 1).unwrap(), text));
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx));
multibuffer.push_excerpts(
buffer,
ranges.into_iter().map(|range| ExcerptRange {
@@ -32,9 +32,9 @@ use crate::{
AppMetadata, AssetCache, AssetSource, BackgroundExecutor, ClipboardItem, Context,
DispatchPhase, DisplayId, Entity, EventEmitter, ForegroundExecutor, Global, KeyBinding, Keymap,
Keystroke, LayoutId, Menu, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point,
- PromptBuilder, PromptHandle, PromptLevel, Render, RenderablePromptHandle, SharedString,
- SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, View, ViewContext, Window,
- WindowAppearance, WindowContext, WindowHandle, WindowId,
+ PromptBuilder, PromptHandle, PromptLevel, Render, RenderablePromptHandle, Reservation,
+ SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, View, ViewContext,
+ Window, WindowAppearance, WindowContext, WindowHandle, WindowId,
};
mod async_context;
@@ -1251,6 +1251,22 @@ impl Context for AppContext {
})
}
+ fn reserve_model<T: 'static>(&mut self) -> Self::Result<Reservation<T>> {
+ Reservation(self.entities.reserve())
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>> {
+ self.update(|cx| {
+ let slot = reservation.0;
+ let entity = build_model(&mut ModelContext::new(cx, slot.downgrade()));
+ cx.entities.insert(slot, entity)
+ })
+ }
+
/// Updates the entity referenced by the given model. The function is passed a mutable reference to the
/// entity along with a `ModelContext` for the entity.
fn update_model<T: 'static, R>(
@@ -1266,6 +1282,18 @@ impl Context for AppContext {
})
}
+ fn read_model<T, R>(
+ &self,
+ handle: &Model<T>,
+ read: impl FnOnce(&T, &AppContext) -> R,
+ ) -> Self::Result<R>
+ where
+ T: 'static,
+ {
+ let entity = self.entities.read(handle);
+ read(entity, self)
+ }
+
fn update_window<T, F>(&mut self, handle: AnyWindowHandle, update: F) -> Result<T>
where
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
@@ -1295,18 +1323,6 @@ impl Context for AppContext {
})
}
- fn read_model<T, R>(
- &self,
- handle: &Model<T>,
- read: impl FnOnce(&T, &AppContext) -> R,
- ) -> Self::Result<R>
- where
- T: 'static,
- {
- let entity = self.entities.read(handle);
- read(entity, self)
- }
-
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
@@ -1,7 +1,7 @@
use crate::{
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, BorrowAppContext, Context,
- DismissEvent, FocusableView, ForegroundExecutor, Global, Model, ModelContext, Render, Result,
- Task, View, ViewContext, VisualContext, WindowContext, WindowHandle,
+ DismissEvent, FocusableView, ForegroundExecutor, Global, Model, ModelContext, Render,
+ Reservation, Result, Task, View, ViewContext, VisualContext, WindowContext, WindowHandle,
};
use anyhow::{anyhow, Context as _};
use derive_more::{Deref, DerefMut};
@@ -35,6 +35,28 @@ impl Context for AsyncAppContext {
Ok(app.new_model(build_model))
}
+ fn reserve_model<T: 'static>(&mut self) -> Result<Reservation<T>> {
+ let app = self
+ .app
+ .upgrade()
+ .ok_or_else(|| anyhow!("app was released"))?;
+ let mut app = app.borrow_mut();
+ Ok(app.reserve_model())
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Result<Model<T>> {
+ let app = self
+ .app
+ .upgrade()
+ .ok_or_else(|| anyhow!("app was released"))?;
+ let mut app = app.borrow_mut();
+ Ok(app.insert_model(reservation, build_model))
+ }
+
fn update_model<T: 'static, R>(
&mut self,
handle: &Model<T>,
@@ -278,6 +300,19 @@ impl Context for AsyncWindowContext {
self.window.update(self, |_, cx| cx.new_model(build_model))
}
+ fn reserve_model<T: 'static>(&mut self) -> Result<Reservation<T>> {
+ self.window.update(self, |_, cx| cx.reserve_model())
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>> {
+ self.window
+ .update(self, |_, cx| cx.insert_model(reservation, build_model))
+ }
+
fn update_model<T: 'static, R>(
&mut self,
handle: &Model<T>,
@@ -287,13 +322,6 @@ impl Context for AsyncWindowContext {
.update(self, |_, cx| cx.update_model(handle, update))
}
- fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
- where
- F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
- {
- self.app.update_window(window, update)
- }
-
fn read_model<T, R>(
&self,
handle: &Model<T>,
@@ -305,6 +333,13 @@ impl Context for AsyncWindowContext {
self.app.read_model(handle, read)
}
+ fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
+ where
+ F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
+ {
+ self.app.update_window(window, update)
+ }
+
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
@@ -9,6 +9,7 @@ use std::{
hash::{Hash, Hasher},
marker::PhantomData,
mem,
+ num::NonZeroU64,
sync::{
atomic::{AtomicUsize, Ordering::SeqCst},
Arc, Weak,
@@ -31,6 +32,11 @@ impl From<u64> for EntityId {
}
impl EntityId {
+ /// Converts this entity id to a [NonZeroU64]
+ pub fn as_non_zero_u64(self) -> NonZeroU64 {
+ NonZeroU64::new(self.0.as_ffi()).unwrap()
+ }
+
/// Converts this entity id to a [u64]
pub fn as_u64(self) -> u64 {
self.0.as_ffi()
@@ -128,14 +134,16 @@ impl EntityMap {
dropped_entity_ids
.into_iter()
- .map(|entity_id| {
+ .filter_map(|entity_id| {
let count = ref_counts.counts.remove(entity_id).unwrap();
debug_assert_eq!(
count.load(SeqCst),
0,
"dropped an entity that was referenced"
);
- (entity_id, self.entities.remove(entity_id).unwrap())
+ // If the EntityId was allocated with `Context::reserve`,
+ // the entity may not have been inserted.
+ Some((entity_id, self.entities.remove(entity_id)?))
})
.collect()
}
@@ -1,6 +1,7 @@
use crate::{
AnyView, AnyWindowHandle, AppContext, AsyncAppContext, Context, Effect, Entity, EntityId,
- EventEmitter, Model, Subscription, Task, View, WeakModel, WindowContext, WindowHandle,
+ EventEmitter, Model, Reservation, Subscription, Task, View, WeakModel, WindowContext,
+ WindowHandle,
};
use anyhow::Result;
use derive_more::{Deref, DerefMut};
@@ -229,6 +230,18 @@ impl<'a, T> Context for ModelContext<'a, T> {
self.app.new_model(build_model)
}
+ fn reserve_model<U: 'static>(&mut self) -> Reservation<U> {
+ self.app.reserve_model()
+ }
+
+ fn insert_model<U: 'static>(
+ &mut self,
+ reservation: Reservation<U>,
+ build_model: impl FnOnce(&mut ModelContext<'_, U>) -> U,
+ ) -> Self::Result<Model<U>> {
+ self.app.insert_model(reservation, build_model)
+ }
+
fn update_model<U: 'static, R>(
&mut self,
handle: &Model<U>,
@@ -237,13 +250,6 @@ impl<'a, T> Context for ModelContext<'a, T> {
self.app.update_model(handle, update)
}
- fn update_window<R, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<R>
- where
- F: FnOnce(AnyView, &mut WindowContext<'_>) -> R,
- {
- self.app.update_window(window, update)
- }
-
fn read_model<U, R>(
&self,
handle: &Model<U>,
@@ -255,6 +261,13 @@ impl<'a, T> Context for ModelContext<'a, T> {
self.app.read_model(handle, read)
}
+ fn update_window<R, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<R>
+ where
+ F: FnOnce(AnyView, &mut WindowContext<'_>) -> R,
+ {
+ self.app.update_window(window, update)
+ }
+
fn read_window<U, R>(
&self,
window: &WindowHandle<U>,
@@ -42,6 +42,20 @@ impl Context for TestAppContext {
app.new_model(build_model)
}
+ fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
+ let mut app = self.app.borrow_mut();
+ app.reserve_model()
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: crate::Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>> {
+ let mut app = self.app.borrow_mut();
+ app.insert_model(reservation, build_model)
+ }
+
fn update_model<T: 'static, R>(
&mut self,
handle: &Model<T>,
@@ -803,6 +817,18 @@ impl Context for VisualTestContext {
self.cx.new_model(build_model)
}
+ fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
+ self.cx.reserve_model()
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: crate::Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>> {
+ self.cx.insert_model(reservation, build_model)
+ }
+
fn update_model<T, R>(
&mut self,
handle: &Model<T>,
@@ -165,6 +165,19 @@ pub trait Context {
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
) -> Self::Result<Model<T>>;
+ /// Reserve a slot for a model to be inserted later.
+ /// The returned [Reservation] allows you to obtain the [EntityId] for the future model.
+ fn reserve_model<T: 'static>(&mut self) -> Self::Result<Reservation<T>>;
+
+ /// Insert a new model in the app context based on a [Reservation] previously obtained from [`reserve_model`].
+ ///
+ /// [`reserve_model`]: Self::reserve_model
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>>;
+
/// Update a model in the app context.
fn update_model<T, R>(
&mut self,
@@ -198,6 +211,17 @@ pub trait Context {
T: 'static;
}
+/// Returned by [Context::reserve_model] to later be passed to [Context::insert_model].
+/// Allows you to obtain the [EntityId] for a model before it is created.
+pub struct Reservation<T>(pub(crate) Slot<T>);
+
+impl<T: 'static> Reservation<T> {
+ /// Returns the [EntityId] that will be associated with the model once it is inserted.
+ pub fn entity_id(&self) -> EntityId {
+ self.0.entity_id()
+ }
+}
+
/// This trait is used for the different visual contexts in GPUI that
/// require a window to be present.
pub trait VisualContext: Context {
@@ -1830,6 +1830,18 @@ impl Context for WindowContext<'_> {
self.entities.insert(slot, model)
}
+ fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
+ self.app.reserve_model()
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: crate::Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>> {
+ self.app.insert_model(reservation, build_model)
+ }
+
fn update_model<T: 'static, R>(
&mut self,
model: &Model<T>,
@@ -1844,18 +1856,6 @@ impl Context for WindowContext<'_> {
result
}
- fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
- where
- F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
- {
- if window == self.window.handle {
- let root_view = self.window.root_view.clone().unwrap();
- Ok(update(root_view, self))
- } else {
- window.update(self.app, update)
- }
- }
-
fn read_model<T, R>(
&self,
handle: &Model<T>,
@@ -1868,6 +1868,18 @@ impl Context for WindowContext<'_> {
read(entity, &*self.app)
}
+ fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
+ where
+ F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
+ {
+ if window == self.window.handle {
+ let root_view = self.window.root_view.clone().unwrap();
+ Ok(update(root_view, self))
+ } else {
+ window.update(self.app, update)
+ }
+ }
+
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
@@ -2478,6 +2490,18 @@ impl<V> Context for ViewContext<'_, V> {
self.window_cx.new_model(build_model)
}
+ fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
+ self.window_cx.reserve_model()
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: crate::Reservation<T>,
+ build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>> {
+ self.window_cx.insert_model(reservation, build_model)
+ }
+
fn update_model<T: 'static, R>(
&mut self,
model: &Model<T>,
@@ -2486,13 +2510,6 @@ impl<V> Context for ViewContext<'_, V> {
self.window_cx.update_model(model, update)
}
- fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
- where
- F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
- {
- self.window_cx.update_window(window, update)
- }
-
fn read_model<T, R>(
&self,
handle: &Model<T>,
@@ -2504,6 +2521,13 @@ impl<V> Context for ViewContext<'_, V> {
self.window_cx.read_model(handle, read)
}
+ fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
+ where
+ F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
+ {
+ self.window_cx.update_window(window, update)
+ }
+
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
@@ -264,6 +264,18 @@ impl<'a> Context for ElementContext<'a> {
self.cx.new_model(build_model)
}
+ fn reserve_model<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
+ self.cx.reserve_model()
+ }
+
+ fn insert_model<T: 'static>(
+ &mut self,
+ reservation: crate::Reservation<T>,
+ build_model: impl FnOnce(&mut crate::ModelContext<'_, T>) -> T,
+ ) -> Self::Result<crate::Model<T>> {
+ self.cx.insert_model(reservation, build_model)
+ }
+
fn update_model<T, R>(
&mut self,
handle: &crate::Model<T>,
@@ -503,9 +503,9 @@ pub enum CharKind {
impl Buffer {
/// Create a new buffer with the given base text.
- pub fn new<T: Into<String>>(replica_id: ReplicaId, id: BufferId, base_text: T) -> Self {
+ pub fn local<T: Into<String>>(base_text: T, cx: &mut ModelContext<Self>) -> Self {
Self::build(
- TextBuffer::new(replica_id, id, base_text.into()),
+ TextBuffer::new(0, cx.entity_id().as_non_zero_u64().into(), base_text.into()),
None,
None,
Capability::ReadWrite,
@@ -517,10 +517,10 @@ impl Buffer {
remote_id: BufferId,
replica_id: ReplicaId,
capability: Capability,
- base_text: String,
+ base_text: impl Into<String>,
) -> Self {
Self::build(
- TextBuffer::new(replica_id, remote_id, base_text),
+ TextBuffer::new(replica_id, remote_id, base_text.into()),
None,
None,
capability,
@@ -44,12 +44,8 @@ fn test_line_endings(cx: &mut gpui::AppContext) {
init_settings(cx, |_| {});
cx.new_model(|cx| {
- let mut buffer = Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "one\r\ntwo\rthree",
- )
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer =
+ Buffer::local("one\r\ntwo\rthree", cx).with_language(Arc::new(rust_lang()), cx);
assert_eq!(buffer.text(), "one\ntwo\nthree");
assert_eq!(buffer.line_ending(), LineEnding::Windows);
@@ -256,10 +252,15 @@ fn test_edit_events(cx: &mut gpui::AppContext) {
let buffer_1_events = Arc::new(Mutex::new(Vec::new()));
let buffer_2_events = Arc::new(Mutex::new(Vec::new()));
- let buffer1 = cx
- .new_model(|cx| Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abcdef"));
- let buffer2 = cx
- .new_model(|cx| Buffer::new(1, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abcdef"));
+ let buffer1 = cx.new_model(|cx| Buffer::local("abcdef", cx));
+ let buffer2 = cx.new_model(|cx| {
+ Buffer::remote(
+ BufferId::from(cx.entity_id().as_non_zero_u64()),
+ 1,
+ Capability::ReadWrite,
+ "abcdef",
+ )
+ });
let buffer1_ops = Arc::new(Mutex::new(Vec::new()));
buffer1.update(cx, {
let buffer1_ops = buffer1_ops.clone();
@@ -338,8 +339,7 @@ fn test_edit_events(cx: &mut gpui::AppContext) {
#[gpui::test]
async fn test_apply_diff(cx: &mut TestAppContext) {
let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
- let buffer =
- cx.new_model(|cx| Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text));
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx));
let anchor = buffer.update(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
let text = "a\nccc\ndddd\nffffff\n";
@@ -371,8 +371,7 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
]
.join("\n");
- let buffer =
- cx.new_model(|cx| Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text));
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx));
// Spawn a task to format the buffer's whitespace.
// Pause so that the foratting task starts running.
@@ -436,10 +435,8 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_reparse(cx: &mut gpui::TestAppContext) {
let text = "fn a() {}";
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx)
- });
+ let buffer =
+ cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
// Wait for the initial text to parse
cx.executor().run_until_parked();
@@ -566,8 +563,7 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) {
#[gpui::test]
async fn test_resetting_language(cx: &mut gpui::TestAppContext) {
let buffer = cx.new_model(|cx| {
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "{}")
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer = Buffer::local("{}", cx).with_language(Arc::new(rust_lang()), cx);
buffer.set_sync_parse_timeout(Duration::ZERO);
buffer
});
@@ -615,10 +611,8 @@ async fn test_outline(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx)
- });
+ let buffer =
+ cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let outline = buffer
.update(cx, |buffer, _| buffer.snapshot().outline(None))
.unwrap();
@@ -702,10 +696,8 @@ async fn test_outline_nodes_with_newlines(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx)
- });
+ let buffer =
+ cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let outline = buffer
.update(cx, |buffer, _| buffer.snapshot().outline(None))
.unwrap();
@@ -741,10 +733,7 @@ async fn test_outline_with_extra_context(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(language), cx)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(language), cx));
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
// extra context nodes are included in the outline.
@@ -786,10 +775,8 @@ async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx)
- });
+ let buffer =
+ cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
// point is at the start of an item
@@ -1010,8 +997,7 @@ fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &
fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
cx.new_model(|cx| {
let text = "fn a() { b(|c| {}) }";
- let buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx);
+ let buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
let snapshot = buffer.snapshot();
assert_eq!(
@@ -1051,8 +1037,7 @@ fn test_autoindent_with_soft_tabs(cx: &mut AppContext) {
cx.new_model(|cx| {
let text = "fn a() {}";
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
assert_eq!(buffer.text(), "fn a() {\n \n}");
@@ -1094,8 +1079,7 @@ fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
cx.new_model(|cx| {
let text = "fn a() {}";
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
assert_eq!(buffer.text(), "fn a() {\n\t\n}");
@@ -1134,9 +1118,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
init_settings(cx, |_| {});
cx.new_model(|cx| {
- let mut buffer = Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
+ let mut buffer = Buffer::local(
"
fn a() {
c;
@@ -1144,6 +1126,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
}
"
.unindent(),
+ cx,
)
.with_language(Arc::new(rust_lang()), cx);
@@ -1209,9 +1192,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
cx.new_model(|cx| {
eprintln!("second buffer: {:?}", cx.entity_id());
- let mut buffer = Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
+ let mut buffer = Buffer::local(
"
fn a() {
b();
@@ -1219,6 +1200,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
"
.replace('|', "") // marker to preserve trailing whitespace
.unindent(),
+ cx,
)
.with_language(Arc::new(rust_lang()), cx);
@@ -1274,15 +1256,14 @@ fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut Ap
init_settings(cx, |_| {});
cx.new_model(|cx| {
- let mut buffer = Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
+ let mut buffer = Buffer::local(
"
fn a() {
i
}
"
.unindent(),
+ cx,
)
.with_language(Arc::new(rust_lang()), cx);
@@ -1336,13 +1317,12 @@ fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
init_settings(cx, |_| {});
cx.new_model(|cx| {
- let mut buffer = Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
+ let mut buffer = Buffer::local(
"
fn a() {}
"
.unindent(),
+ cx,
)
.with_language(Arc::new(rust_lang()), cx);
@@ -1394,8 +1374,7 @@ fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
cx.new_model(|cx| {
let text = "a\nb";
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
buffer.edit(
[(0..1, "\n"), (2..3, "\n")],
Some(AutoindentMode::EachLine),
@@ -1421,8 +1400,7 @@ fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
"
.unindent();
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
buffer.edit(
[(Point::new(3, 0)..Point::new(3, 0), "e(\n f()\n);\n")],
Some(AutoindentMode::EachLine),
@@ -1459,8 +1437,7 @@ fn test_autoindent_block_mode(cx: &mut AppContext) {
}
"#
.unindent();
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
// When this text was copied, both of the quotation marks were at the same
// indent level, but the indentation of the first line was not included in
@@ -1545,8 +1522,7 @@ fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContex
}
"#
.unindent();
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(Arc::new(rust_lang()), cx);
+ let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx);
// The original indent columns are not known, so this text is
// auto-indented in a block as if the first line was copied in
@@ -1625,18 +1601,17 @@ fn test_autoindent_language_without_indents_query(cx: &mut AppContext) {
"
.unindent();
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(
- Arc::new(Language::new(
- LanguageConfig {
- name: "Markdown".into(),
- auto_indent_using_last_non_empty_line: false,
- ..Default::default()
- },
- Some(tree_sitter_json::language()),
- )),
- cx,
- );
+ let mut buffer = Buffer::local(text, cx).with_language(
+ Arc::new(Language::new(
+ LanguageConfig {
+ name: "Markdown".into(),
+ auto_indent_using_last_non_empty_line: false,
+ ..Default::default()
+ },
+ Some(tree_sitter_json::language()),
+ )),
+ cx,
+ );
buffer.edit(
[(Point::new(3, 0)..Point::new(3, 0), "\n")],
Some(AutoindentMode::EachLine),
@@ -1702,7 +1677,7 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
false,
);
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text);
+ let mut buffer = Buffer::local(text, cx);
buffer.set_language_registry(language_registry);
buffer.set_language(Some(html_language), cx);
buffer.edit(
@@ -1738,8 +1713,7 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
});
cx.new_model(|cx| {
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "")
- .with_language(Arc::new(ruby_lang()), cx);
+ let mut buffer = Buffer::local("", cx).with_language(Arc::new(ruby_lang()), cx);
let text = r#"
class C
@@ -1840,8 +1814,7 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
"#
.unindent();
- let buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), &text)
- .with_language(Arc::new(language), cx);
+ let buffer = Buffer::local(&text, cx).with_language(Arc::new(language), cx);
let snapshot = buffer.snapshot();
let config = snapshot.language_scope_at(0).unwrap();
@@ -1958,12 +1931,7 @@ fn test_language_scope_at_with_rust(cx: &mut AppContext) {
"#
.unindent();
- let buffer = Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- text.clone(),
- )
- .with_language(Arc::new(language), cx);
+ let buffer = Buffer::local(text.clone(), cx).with_language(Arc::new(language), cx);
let snapshot = buffer.snapshot();
// By default, all brackets are enabled
@@ -2007,7 +1975,7 @@ fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
language_registry.add(Arc::new(html_lang()));
language_registry.add(Arc::new(erb_lang()));
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text);
+ let mut buffer = Buffer::local(text, cx);
buffer.set_language_registry(language_registry.clone());
buffer.set_language(
language_registry
@@ -2042,7 +2010,7 @@ fn test_serialization(cx: &mut gpui::AppContext) {
let mut now = Instant::now();
let buffer1 = cx.new_model(|cx| {
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abc");
+ let mut buffer = Buffer::local("abc", cx);
buffer.edit([(3..3, "D")], None, cx);
now += Duration::from_secs(1);
@@ -2097,13 +2065,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
let mut replica_ids = Vec::new();
let mut buffers = Vec::new();
let network = Arc::new(Mutex::new(Network::new(rng.clone())));
- let base_buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- base_text.as_str(),
- )
- });
+ let base_buffer = cx.new_model(|cx| Buffer::local(base_text.as_str(), cx));
for i in 0..rng.gen_range(min_peers..=max_peers) {
let buffer = cx.new_model(|cx| {
@@ -2623,12 +2585,7 @@ fn assert_bracket_pairs(
) {
let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false);
let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- expected_text.clone(),
- )
- .with_language(Arc::new(language), cx)
+ Buffer::local(expected_text.clone(), cx).with_language(Arc::new(language), cx)
});
let buffer = buffer.update(cx, |buffer, _cx| buffer.snapshot());
@@ -297,7 +297,6 @@ mod tests {
use language::{language_settings::AllLanguageSettings, AutoindentMode, Buffer};
use settings::SettingsStore;
use std::num::NonZeroU32;
- use text::BufferId;
#[gpui::test]
async fn test_c_autoindent(cx: &mut TestAppContext) {
@@ -315,8 +314,7 @@ mod tests {
let language = crate::language("c", tree_sitter_c::language());
cx.new_model(|cx| {
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "")
- .with_language(language, cx);
+ let mut buffer = Buffer::local("", cx).with_language(language, cx);
// empty function
buffer.edit([(0..0, "int main() {}")], None, cx);
@@ -136,7 +136,6 @@ async fn get_cached_server_binary(
#[cfg(test)]
mod tests {
use gpui::{Context, TestAppContext};
- use text::BufferId;
use unindent::Unindent;
#[gpui::test]
@@ -168,10 +167,8 @@ mod tests {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- language::Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer =
+ cx.new_model(|cx| language::Buffer::local(text, cx).with_language(language, cx));
let outline = buffer.update(cx, |buffer, _| buffer.snapshot().outline(None).unwrap());
assert_eq!(
outline
@@ -186,7 +186,6 @@ mod tests {
use language::{language_settings::AllLanguageSettings, AutoindentMode, Buffer};
use settings::SettingsStore;
use std::num::NonZeroU32;
- use text::BufferId;
#[gpui::test]
async fn test_python_autoindent(cx: &mut TestAppContext) {
@@ -204,8 +203,7 @@ mod tests {
});
cx.new_model(|cx| {
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "")
- .with_language(language, cx);
+ let mut buffer = Buffer::local("", cx).with_language(language, cx);
let append = |buffer: &mut Buffer, text: &str, cx: &mut ModelContext<Buffer>| {
let ix = buffer.len();
buffer.edit([(ix..ix, text)], Some(AutoindentMode::EachLine), cx);
@@ -465,7 +465,6 @@ mod tests {
use gpui::{BorrowAppContext, Context, Hsla, TestAppContext};
use language::language_settings::AllLanguageSettings;
use settings::SettingsStore;
- use text::BufferId;
use theme::SyntaxTheme;
#[gpui::test]
@@ -682,8 +681,7 @@ mod tests {
let language = crate::language("rust", tree_sitter_rust::language());
cx.new_model(|cx| {
- let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "")
- .with_language(language, cx);
+ let mut buffer = Buffer::local("", cx).with_language(language, cx);
// indent between braces
buffer.set_text("fn a() {}", cx);
@@ -413,7 +413,6 @@ async fn get_cached_eslint_server_binary(
#[cfg(test)]
mod tests {
use gpui::{Context, TestAppContext};
- use text::BufferId;
use unindent::Unindent;
#[gpui::test]
@@ -435,10 +434,8 @@ mod tests {
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- language::Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- .with_language(language, cx)
- });
+ let buffer =
+ cx.new_model(|cx| language::Buffer::local(text, cx).with_language(language, cx));
let outline = buffer.update(cx, |buffer, _| buffer.snapshot().outline(None).unwrap());
assert_eq!(
outline
@@ -1700,8 +1700,7 @@ impl MultiBuffer {
#[cfg(any(test, feature = "test-support"))]
impl MultiBuffer {
pub fn build_simple(text: &str, cx: &mut gpui::AppContext) -> Model<Self> {
- let buffer = cx
- .new_model(|cx| Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text));
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx));
cx.new_model(|cx| Self::singleton(buffer, cx))
}
@@ -1711,9 +1710,7 @@ impl MultiBuffer {
) -> Model<Self> {
let multi = cx.new_model(|_| Self::new(0, Capability::ReadWrite));
for (text, ranges) in excerpts {
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- });
+ let buffer = cx.new_model(|cx| Buffer::local(text, cx));
let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
context: range,
primary: None,
@@ -1802,9 +1799,7 @@ impl MultiBuffer {
if excerpt_ids.is_empty() || (rng.gen() && excerpt_ids.len() < max_excerpts) {
let buffer_handle = if rng.gen() || self.buffers.borrow().is_empty() {
let text = RandomCharIter::new(&mut *rng).take(10).collect::<String>();
- buffers.push(cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
- }));
+ buffers.push(cx.new_model(|cx| Buffer::local(text, cx)));
let buffer = buffers.last().unwrap().read(cx);
log::info!(
"Creating new buffer {} with text: {:?}",
@@ -4327,13 +4322,7 @@ mod tests {
#[gpui::test]
fn test_singleton(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(6, 6, 'a'),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
@@ -4360,8 +4349,7 @@ mod tests {
#[gpui::test]
fn test_remote(cx: &mut AppContext) {
- let host_buffer =
- cx.new_model(|cx| Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "a"));
+ let host_buffer = cx.new_model(|cx| Buffer::local("a", cx));
let guest_buffer = cx.new_model(|cx| {
let state = host_buffer.read(cx).to_proto();
let ops = cx
@@ -4392,20 +4380,8 @@ mod tests {
#[gpui::test]
fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(6, 6, 'a'),
- )
- });
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(6, 6, 'g'),
- )
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
+ let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
let events = Arc::new(RwLock::new(Vec::<Event>::new()));
@@ -4638,20 +4614,8 @@ mod tests {
#[gpui::test]
fn test_excerpt_events(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(10, 3, 'a'),
- )
- });
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(10, 3, 'm'),
- )
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'a'), cx));
+ let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'm'), cx));
let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
@@ -4756,13 +4720,7 @@ mod tests {
#[gpui::test]
fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(20, 3, 'a'),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
multibuffer.push_excerpts_with_context_lines(
@@ -4798,13 +4756,7 @@ mod tests {
#[gpui::test]
async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) {
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- sample_text(20, 3, 'a'),
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
let snapshot = buffer.read(cx);
@@ -4850,9 +4802,7 @@ mod tests {
#[gpui::test]
fn test_singleton_multibuffer_anchors(cx: &mut AppContext) {
- let buffer = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abcd")
- });
+ let buffer = cx.new_model(|cx| Buffer::local("abcd", cx));
let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let old_snapshot = multibuffer.read(cx).snapshot(cx);
buffer.update(cx, |buffer, cx| {
@@ -4872,12 +4822,8 @@ mod tests {
#[gpui::test]
fn test_multibuffer_anchors(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abcd")
- });
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "efghi")
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
+ let buffer_2 = cx.new_model(|cx| Buffer::local("efghi", cx));
let multibuffer = cx.new_model(|cx| {
let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
multibuffer.push_excerpts(
@@ -4934,16 +4880,8 @@ mod tests {
#[gpui::test]
fn test_resolving_anchors_after_replacing_their_excerpts(cx: &mut AppContext) {
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abcd")
- });
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- "ABCDEFGHIJKLMNOP",
- )
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local("abcd", cx));
+ let buffer_2 = cx.new_model(|cx| Buffer::local("ABCDEFGHIJKLMNOP", cx));
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
// Create an insertion id in buffer 1 that doesn't exist in buffer 2.
@@ -5154,13 +5092,7 @@ mod tests {
let base_text = util::RandomCharIter::new(&mut rng)
.take(10)
.collect::<String>();
- buffers.push(cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- base_text,
- )
- }));
+ buffers.push(cx.new_model(|cx| Buffer::local(base_text, cx)));
buffers.last().unwrap()
} else {
buffers.choose(&mut rng).unwrap()
@@ -5502,12 +5434,8 @@ mod tests {
let test_settings = SettingsStore::test(cx);
cx.set_global(test_settings);
- let buffer_1 = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "1234")
- });
- let buffer_2 = cx.new_model(|cx| {
- Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "5678")
- });
+ let buffer_1 = cx.new_model(|cx| Buffer::local("1234", cx));
+ let buffer_2 = cx.new_model(|cx| Buffer::local("5678", cx));
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
let group_interval = multibuffer.read(cx).history.group_interval;
multibuffer.update(cx, |multibuffer, cx| {
@@ -178,7 +178,6 @@ pub struct Project {
collaborators: HashMap<proto::PeerId, Collaborator>,
client_subscriptions: Vec<client::Subscription>,
_subscriptions: Vec<gpui::Subscription>,
- next_buffer_id: BufferId,
loading_buffers: HashMap<BufferId, Vec<oneshot::Sender<Result<Model<Buffer>, anyhow::Error>>>>,
incomplete_remote_buffers: HashMap<BufferId, Model<Buffer>>,
shared_buffers: HashMap<proto::PeerId, HashSet<BufferId>>,
@@ -675,7 +674,6 @@ impl Project {
flush_language_server_update: None,
pending_language_server_update: None,
collaborators: Default::default(),
- next_buffer_id: BufferId::new(1).unwrap(),
opened_buffers: Default::default(),
shared_buffers: Default::default(),
loading_buffers_by_path: Default::default(),
@@ -792,7 +790,6 @@ impl Project {
pending_language_server_update: None,
flush_language_server_update: None,
loading_buffers_by_path: Default::default(),
- next_buffer_id: BufferId::new(1).unwrap(),
loading_buffers: Default::default(),
shared_buffers: Default::default(),
incomplete_remote_buffers: Default::default(),
@@ -1849,9 +1846,8 @@ impl Project {
if self.is_remote() {
return Err(anyhow!("creating buffers as a guest is not supported yet"));
}
- let id = self.next_buffer_id.next();
let buffer = cx.new_model(|cx| {
- Buffer::new(self.replica_id(), id, text)
+ Buffer::local(text, cx)
.with_language(language.unwrap_or_else(|| language::PLAIN_TEXT.clone()), cx)
});
self.register_buffer(&buffer, cx)?;
@@ -1950,10 +1946,9 @@ impl Project {
worktree: Model<Worktree>,
cx: &mut ModelContext<Self>,
) -> Task<Result<Model<Buffer>>> {
- let buffer_id = self.next_buffer_id.next();
let load_buffer = worktree.update(cx, |worktree, cx| {
let worktree = worktree.as_local_mut().unwrap();
- worktree.load_buffer(buffer_id, &path, cx)
+ worktree.load_buffer(&path, cx)
});
fn is_not_found_error(error: &anyhow::Error) -> bool {
error
@@ -1967,7 +1962,7 @@ impl Project {
Err(error) if is_not_found_error(&error) => {
worktree.update(&mut cx, |worktree, cx| {
let worktree = worktree.as_local_mut().unwrap();
- worktree.new_buffer(buffer_id, path, cx)
+ worktree.new_buffer(path, cx)
})
}
Err(e) => Err(e),
@@ -1141,7 +1141,7 @@ mod tests {
use super::*;
use editor::{DisplayPoint, Editor};
use gpui::{Context, Hsla, TestAppContext, VisualTestContext};
- use language::{Buffer, BufferId};
+ use language::Buffer;
use smol::stream::StreamExt as _;
use unindent::Unindent as _;
@@ -1161,9 +1161,7 @@ mod tests {
) -> (View<Editor>, View<BufferSearchBar>, &mut VisualTestContext) {
init_globals(cx);
let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
+ Buffer::local(
r#"
A regular expression (shortened as regex or regexp;[1] also referred to as
rational expression[2][3]) is a sequence of characters that specifies a search
@@ -1171,6 +1169,7 @@ mod tests {
for "find" or "find and replace" operations on strings, or for input validation.
"#
.unindent(),
+ cx,
)
});
let cx = cx.add_empty_window();
@@ -1519,13 +1518,7 @@ mod tests {
expected_query_matches_count > 1,
"Should pick a query with multiple results"
);
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- buffer_text,
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(buffer_text, cx));
let window = cx.add_window(|_| gpui::Empty);
let editor = window.build_view(cx, |cx| Editor::for_buffer(buffer.clone(), None, cx));
@@ -1721,13 +1714,7 @@ mod tests {
for "find" or "find and replace" operations on strings, or for input validation.
"#
.unindent();
- let buffer = cx.new_model(|cx| {
- Buffer::new(
- 0,
- BufferId::new(cx.entity_id().as_u64()).unwrap(),
- buffer_text,
- )
- });
+ let buffer = cx.new_model(|cx| Buffer::local(buffer_text, cx));
let cx = cx.add_empty_window();
let editor = cx.new_view(|cx| Editor::for_buffer(buffer.clone(), None, cx));
@@ -71,12 +71,19 @@ impl Display for BufferId {
}
}
+impl From<NonZeroU64> for BufferId {
+ fn from(id: NonZeroU64) -> Self {
+ BufferId(id)
+ }
+}
+
impl BufferId {
/// Returns Err if `id` is outside of BufferId domain.
pub fn new(id: u64) -> anyhow::Result<Self> {
let id = NonZeroU64::new(id).context("Buffer id cannot be 0.")?;
Ok(Self(id))
}
+
/// Increments this buffer id, returning the old value.
/// So that's a post-increment operator in disguise.
pub fn next(&mut self) -> Self {
@@ -73,14 +73,14 @@ mod test {
use crate::{test::VimTestContext, Vim};
use editor::Editor;
use gpui::{Context, Entity, VisualTestContext};
- use language::{Buffer, BufferId};
+ use language::Buffer;
// regression test for blur called with a different active editor
#[gpui::test]
async fn test_blur_focus(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
- let buffer = cx.new_model(|_| Buffer::new(0, BufferId::new(1).unwrap(), "a = 1\nb = 2\n"));
+ let buffer = cx.new_model(|cx| Buffer::local("a = 1\nb = 2\n", cx));
let window2 = cx.add_window(|cx| Editor::for_buffer(buffer, None, cx));
let editor2 = cx
.update(|cx| {
@@ -115,7 +115,7 @@ mod test {
let mut cx1 = VisualTestContext::from_window(cx.window, &cx);
let editor1 = cx.editor.clone();
- let buffer = cx.new_model(|_| Buffer::new(0, BufferId::new(1).unwrap(), "a = 1\nb = 2\n"));
+ let buffer = cx.new_model(|cx| Buffer::local("a = 1\nb = 2\n", cx));
let (editor2, cx2) = cx.add_window_view(|cx| Editor::for_buffer(buffer, None, cx));
editor2.update(cx2, |_, cx| {
@@ -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();