text: Wrap BufferId into a newtype

This commit is contained in:
Piotr Osiewicz
2024-01-29 20:00:47 +01:00
parent 941e838be9
commit 5ab715aac9
34 changed files with 687 additions and 383 deletions
+12 -10
View File
@@ -15,7 +15,7 @@ use crate::{
},
CodeLabel, LanguageScope, Outline,
};
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context, Result};
pub use clock::ReplicaId;
use futures::channel::oneshot;
use gpui::{AppContext, EventEmitter, HighlightStyle, ModelContext, Task, TaskLabel};
@@ -44,10 +44,10 @@ use sum_tree::TreeMap;
use text::operation_queue::OperationQueue;
use text::*;
pub use text::{
Anchor, Bias, Buffer as TextBuffer, BufferSnapshot as TextBufferSnapshot, Edit, OffsetRangeExt,
OffsetUtf16, Patch, Point, PointUtf16, Rope, RopeFingerprint, Selection, SelectionGoal,
Subscription, TextDimension, TextSummary, ToOffset, ToOffsetUtf16, ToPoint, ToPointUtf16,
Transaction, TransactionId, Unclipped,
Anchor, Bias, Buffer as TextBuffer, BufferId, BufferSnapshot as TextBufferSnapshot, Edit,
OffsetRangeExt, OffsetUtf16, Patch, Point, PointUtf16, Rope, RopeFingerprint, Selection,
SelectionGoal, Subscription, TextDimension, TextSummary, ToOffset, ToOffsetUtf16, ToPoint,
ToPointUtf16, Transaction, TransactionId, Unclipped,
};
use theme::SyntaxTheme;
#[cfg(any(test, feature = "test-support"))]
@@ -396,7 +396,7 @@ pub trait LocalFile: File {
/// Called when the buffer is reloaded from disk.
fn buffer_reloaded(
&self,
buffer_id: u64,
buffer_id: BufferId,
version: &clock::Global,
fingerprint: RopeFingerprint,
line_ending: LineEnding,
@@ -517,7 +517,7 @@ pub enum CharKind {
impl Buffer {
/// Create a new buffer with the given base text.
pub fn new<T: Into<String>>(replica_id: ReplicaId, id: u64, base_text: T) -> Self {
pub fn new<T: Into<String>>(replica_id: ReplicaId, id: BufferId, base_text: T) -> Self {
Self::build(
TextBuffer::new(replica_id, id, base_text.into()),
None,
@@ -528,7 +528,7 @@ impl Buffer {
/// Create a new buffer that is a replica of a remote buffer.
pub fn remote(
remote_id: u64,
remote_id: BufferId,
replica_id: ReplicaId,
capability: Capability,
base_text: String,
@@ -549,7 +549,9 @@ impl Buffer {
message: proto::BufferState,
file: Option<Arc<dyn File>>,
) -> Result<Self> {
let buffer = TextBuffer::new(replica_id, message.id, message.base_text);
let buffer_id = BufferId::new(message.id)
.with_context(|| anyhow!("Could not deserialize buffer_id"))?;
let buffer = TextBuffer::new(replica_id, buffer_id, message.base_text);
let mut this = Self::build(
buffer,
message.diff_base.map(|text| text.into_boxed_str().into()),
@@ -572,7 +574,7 @@ impl Buffer {
/// Serialize the buffer's state to a protobuf message.
pub fn to_proto(&self) -> proto::BufferState {
proto::BufferState {
id: self.remote_id(),
id: self.remote_id().into(),
file: self.file.as_ref().map(|f| f.to_proto()),
base_text: self.base_text().to_string(),
diff_base: self.diff_base.as_ref().map(|h| h.to_string()),
+83 -57
View File
@@ -18,7 +18,7 @@ use std::{
time::{Duration, Instant},
};
use text::network::Network;
use text::LineEnding;
use text::{BufferId, LineEnding};
use text::{Point, ToPoint};
use unindent::Unindent as _;
use util::{assert_set_eq, post_inc, test::marked_text_ranges, RandomCharIter};
@@ -43,8 +43,12 @@ fn test_line_endings(cx: &mut gpui::AppContext) {
init_settings(cx, |_| {});
cx.new_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "one\r\ntwo\rthree")
.with_language(Arc::new(rust_lang()), 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);
assert_eq!(buffer.text(), "one\ntwo\nthree");
assert_eq!(buffer.line_ending(), LineEnding::Windows);
@@ -138,8 +142,10 @@ 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, cx.entity_id().as_u64(), "abcdef"));
let buffer2 = cx.new_model(|cx| Buffer::new(1, cx.entity_id().as_u64(), "abcdef"));
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_ops = Arc::new(Mutex::new(Vec::new()));
buffer1.update(cx, {
let buffer1_ops = buffer1_ops.clone();
@@ -218,7 +224,8 @@ 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, cx.entity_id().as_u64(), text));
let buffer =
cx.new_model(|cx| Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text));
let anchor = buffer.update(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
let text = "a\nccc\ndddd\nffffff\n";
@@ -250,7 +257,8 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
]
.join("\n");
let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
let buffer =
cx.new_model(|cx| Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text));
// Spawn a task to format the buffer's whitespace.
// Pause so that the foratting task starts running.
@@ -315,7 +323,8 @@ async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
async fn test_reparse(cx: &mut gpui::TestAppContext) {
let text = "fn a() {}";
let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.with_language(Arc::new(rust_lang()), cx)
});
// Wait for the initial text to parse
@@ -443,8 +452,8 @@ 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, cx.entity_id().as_u64(), "{}").with_language(Arc::new(rust_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "{}")
.with_language(Arc::new(rust_lang()), cx);
buffer.set_sync_parse_timeout(Duration::ZERO);
buffer
});
@@ -493,7 +502,8 @@ async fn test_outline(cx: &mut gpui::TestAppContext) {
.unindent();
let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.with_language(Arc::new(rust_lang()), cx)
});
let outline = buffer
.update(cx, |buffer, _| buffer.snapshot().outline(None))
@@ -579,7 +589,8 @@ async fn test_outline_nodes_with_newlines(cx: &mut gpui::TestAppContext) {
.unindent();
let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.with_language(Arc::new(rust_lang()), cx)
});
let outline = buffer
.update(cx, |buffer, _| buffer.snapshot().outline(None))
@@ -617,7 +628,8 @@ async fn test_outline_with_extra_context(cx: &mut gpui::TestAppContext) {
.unindent();
let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(language), cx)
Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.with_language(Arc::new(language), cx)
});
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
@@ -661,7 +673,8 @@ async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
.unindent();
let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.with_language(Arc::new(rust_lang()), cx)
});
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
@@ -883,8 +896,8 @@ 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, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
let buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.with_language(Arc::new(rust_lang()), cx);
let snapshot = buffer.snapshot();
assert_eq!(
@@ -924,8 +937,8 @@ fn test_autoindent_with_soft_tabs(cx: &mut AppContext) {
cx.new_model(|cx| {
let text = "fn a() {}";
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.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}");
@@ -967,8 +980,8 @@ fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
cx.new_model(|cx| {
let text = "fn a() {}";
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.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}");
@@ -1007,10 +1020,9 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
init_settings(cx, |_| {});
cx.new_model(|cx| {
let entity_id = cx.entity_id();
let mut buffer = Buffer::new(
0,
entity_id.as_u64(),
BufferId::new(cx.entity_id().as_u64()).unwrap(),
"
fn a() {
c;
@@ -1085,7 +1097,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
let mut buffer = Buffer::new(
0,
cx.entity_id().as_u64(),
BufferId::new(cx.entity_id().as_u64()).unwrap(),
"
fn a() {
b();
@@ -1150,7 +1162,7 @@ fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut Ap
cx.new_model(|cx| {
let mut buffer = Buffer::new(
0,
cx.entity_id().as_u64(),
BufferId::new(cx.entity_id().as_u64()).unwrap(),
"
fn a() {
i
@@ -1212,7 +1224,7 @@ fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
cx.new_model(|cx| {
let mut buffer = Buffer::new(
0,
cx.entity_id().as_u64(),
BufferId::new(cx.entity_id().as_u64()).unwrap(),
"
fn a() {}
"
@@ -1268,8 +1280,8 @@ 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, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.with_language(Arc::new(rust_lang()), cx);
buffer.edit(
[(0..1, "\n"), (2..3, "\n")],
Some(AutoindentMode::EachLine),
@@ -1295,8 +1307,8 @@ fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
"
.unindent();
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.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),
@@ -1333,8 +1345,8 @@ fn test_autoindent_block_mode(cx: &mut AppContext) {
}
"#
.unindent();
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.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
@@ -1419,8 +1431,8 @@ fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContex
}
"#
.unindent();
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text)
.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
@@ -1499,17 +1511,18 @@ fn test_autoindent_language_without_indents_query(cx: &mut AppContext) {
"
.unindent();
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), 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::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,
);
buffer.edit(
[(Point::new(3, 0)..Point::new(3, 0), "\n")],
Some(AutoindentMode::EachLine),
@@ -1575,7 +1588,7 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
false,
);
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), text);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text);
buffer.set_language_registry(language_registry);
buffer.set_language(Some(html_language), cx);
buffer.edit(
@@ -1611,8 +1624,8 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
});
cx.new_model(|cx| {
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), "").with_language(Arc::new(ruby_lang()), cx);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "")
.with_language(Arc::new(ruby_lang()), cx);
let text = r#"
class C
@@ -1713,8 +1726,8 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
"#
.unindent();
let buffer =
Buffer::new(0, cx.entity_id().as_u64(), &text).with_language(Arc::new(language), cx);
let buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), &text)
.with_language(Arc::new(language), cx);
let snapshot = buffer.snapshot();
let config = snapshot.language_scope_at(0).unwrap();
@@ -1831,8 +1844,12 @@ fn test_language_scope_at_with_rust(cx: &mut AppContext) {
"#
.unindent();
let buffer = Buffer::new(0, cx.entity_id().as_u64(), text.clone())
.with_language(Arc::new(language), cx);
let buffer = Buffer::new(
0,
BufferId::new(cx.entity_id().as_u64()).unwrap(),
text.clone(),
)
.with_language(Arc::new(language), cx);
let snapshot = buffer.snapshot();
// By default, all brackets are enabled
@@ -1876,7 +1893,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, cx.entity_id().as_u64(), text);
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), text);
buffer.set_language_registry(language_registry.clone());
buffer.set_language(
language_registry
@@ -1911,7 +1928,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, cx.entity_id().as_u64(), "abc");
let mut buffer = Buffer::new(0, BufferId::new(cx.entity_id().as_u64()).unwrap(), "abc");
buffer.edit([(3..3, "D")], None, cx);
now += Duration::from_secs(1);
@@ -1966,8 +1983,13 @@ 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, cx.entity_id().as_u64(), base_text.as_str()));
let base_buffer = cx.new_model(|cx| {
Buffer::new(
0,
BufferId::new(cx.entity_id().as_u64()).unwrap(),
base_text.as_str(),
)
});
for i in 0..rng.gen_range(min_peers..=max_peers) {
let buffer = cx.new_model(|cx| {
@@ -2475,8 +2497,12 @@ fn assert_bracket_pairs(
) {
let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false);
let buffer = cx.new_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), expected_text.clone())
.with_language(Arc::new(language), cx)
Buffer::new(
0,
BufferId::new(cx.entity_id().as_u64()).unwrap(),
expected_text.clone(),
)
.with_language(Arc::new(language), cx)
});
let buffer = buffer.update(cx, |buffer, _cx| buffer.snapshot());
+7 -2
View File
@@ -241,7 +241,7 @@ pub fn serialize_anchor(anchor: &Anchor) -> proto::Anchor {
Bias::Left => proto::Bias::Left as i32,
Bias::Right => proto::Bias::Right as i32,
},
buffer_id: anchor.buffer_id,
buffer_id: anchor.buffer_id.map(Into::into),
}
}
@@ -420,6 +420,11 @@ pub fn deserialize_diagnostics(
/// Deserializes an [`Anchor`] from the RPC representation.
pub fn deserialize_anchor(anchor: proto::Anchor) -> Option<Anchor> {
let buffer_id = if let Some(id) = anchor.buffer_id {
Some(BufferId::new(id).ok()?)
} else {
None
};
Some(Anchor {
timestamp: clock::Lamport {
replica_id: anchor.replica_id as ReplicaId,
@@ -430,7 +435,7 @@ pub fn deserialize_anchor(anchor: proto::Anchor) -> Option<Anchor> {
proto::Bias::Left => Bias::Left,
proto::Bias::Right => Bias::Right,
},
buffer_id: anchor.buffer_id,
buffer_id,
})
}
@@ -2,7 +2,7 @@ use super::*;
use crate::LanguageConfig;
use rand::rngs::StdRng;
use std::{env, ops::Range, sync::Arc};
use text::Buffer;
use text::{Buffer, BufferId};
use tree_sitter::Node;
use unindent::Unindent as _;
use util::test::marked_text_ranges;
@@ -86,7 +86,7 @@ fn test_syntax_map_layers_for_range() {
let mut buffer = Buffer::new(
0,
0,
BufferId::new(1).unwrap(),
r#"
fn a() {
assert_eq!(
@@ -185,7 +185,7 @@ fn test_dynamic_language_injection() {
let mut buffer = Buffer::new(
0,
0,
BufferId::new(1).unwrap(),
r#"
This is a code block:
@@ -860,7 +860,7 @@ fn test_random_edits(
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
let mut buffer = Buffer::new(0, 0, text);
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), text);
let mut syntax_map = SyntaxMap::new();
syntax_map.set_language_registry(registry.clone());
@@ -1040,7 +1040,7 @@ fn test_edit_sequence(language_name: &str, steps: &[&str]) -> (Buffer, SyntaxMap
.now_or_never()
.unwrap()
.unwrap();
let mut buffer = Buffer::new(0, 0, Default::default());
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), Default::default());
let mut mutated_syntax_map = SyntaxMap::new();
mutated_syntax_map.set_language_registry(registry.clone());