diff --git a/crates/buffer_diff/src/buffer_diff.rs b/crates/buffer_diff/src/buffer_diff.rs index 1787f616ad365175de352e3eeeede3e1749dede4..13479f6428b02d52f45415a989b694cc04ab5c25 100644 --- a/crates/buffer_diff/src/buffer_diff.rs +++ b/crates/buffer_diff/src/buffer_diff.rs @@ -118,11 +118,11 @@ impl sum_tree::Summary for DiffHunkSummary { } fn add_summary(&mut self, other: &Self, buffer: Self::Context<'_>) { - self.buffer_range.start = self + self.buffer_range.start = *self .buffer_range .start .min(&other.buffer_range.start, buffer); - self.buffer_range.end = self.buffer_range.end.max(&other.buffer_range.end, buffer); + self.buffer_range.end = *self.buffer_range.end.max(&other.buffer_range.end, buffer); } } @@ -1068,8 +1068,8 @@ impl BufferDiff { self.range_to_hunk_range(secondary_changed_range, buffer, cx) { if let Some(range) = &mut changed_range { - range.start = secondary_hunk_range.start.min(&range.start, buffer); - range.end = secondary_hunk_range.end.max(&range.end, buffer); + range.start = *secondary_hunk_range.start.min(&range.start, buffer); + range.end = *secondary_hunk_range.end.max(&range.end, buffer); } else { changed_range = Some(secondary_hunk_range); } @@ -1083,8 +1083,8 @@ impl BufferDiff { if let Some((first, last)) = state.pending_hunks.first().zip(state.pending_hunks.last()) { if let Some(range) = &mut changed_range { - range.start = range.start.min(&first.buffer_range.start, buffer); - range.end = range.end.max(&last.buffer_range.end, buffer); + range.start = *range.start.min(&first.buffer_range.start, buffer); + range.end = *range.end.max(&last.buffer_range.end, buffer); } else { changed_range = Some(first.buffer_range.start..last.buffer_range.end); } diff --git a/crates/clock/src/clock.rs b/crates/clock/src/clock.rs index b4f57116d273733d6c43a0a09c8a2a33ccb89b38..64645c9b46f68416c6792b17258baf8e49ca9585 100644 --- a/crates/clock/src/clock.rs +++ b/crates/clock/src/clock.rs @@ -206,7 +206,13 @@ impl Lamport { impl fmt::Debug for Lamport { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Lamport {{{}: {}}}", self.replica_id, self.value) + if *self == Self::MAX { + write!(f, "Lamport {{MAX}}") + } else if *self == Self::MIN { + write!(f, "Lamport {{MIN}}") + } else { + write!(f, "Lamport {{{}: {}}}", self.replica_id, self.value) + } } } @@ -219,6 +225,8 @@ impl fmt::Debug for Global { } if timestamp.replica_id == LOCAL_BRANCH_REPLICA_ID { write!(f, ": {}", timestamp.value)?; + } else if timestamp.replica_id == AGENT_REPLICA_ID { + write!(f, ": {}", timestamp.value)?; } else { write!(f, "{}: {}", timestamp.replica_id, timestamp.value)?; } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 15af61f5d28336f77976ee3fadc783016cc283bd..5d881f221b238c35224f804c1b95094a2db957e8 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -6887,7 +6887,8 @@ impl Editor { continue; } - let range = Anchor::range_in_buffer(excerpt_id, buffer_id, start..end); + let range = + Anchor::range_in_buffer(excerpt_id, buffer_id, *start..*end); if highlight.kind == lsp::DocumentHighlightKind::WRITE { write_ranges.push(range); } else { diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 290c8892d9c93ee805ee8106bab183921f616099..f71110ed95d13eba4577e53cf148e8d7efbc20c1 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -7465,7 +7465,7 @@ impl EditorElement { let clipped_start = range.start.max(&buffer_range.start, buffer); let clipped_end = range.end.min(&buffer_range.end, buffer); let range = buffer_snapshot - .anchor_range_in_excerpt(excerpt_id, clipped_start..clipped_end)?; + .anchor_range_in_excerpt(excerpt_id, *clipped_start..*clipped_end)?; let start = range.start.to_display_point(display_snapshot); let end = range.end.to_display_point(display_snapshot); let selection_layout = SelectionLayout { diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index ac769dfdafcf79af51c1f3119453e89d39ca333a..18a619212dba49bf1c384679ec90120af80e0e2a 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -64,17 +64,22 @@ pub struct MultiBuffer { /// Use [`MultiBuffer::snapshot`] to get a up-to-date snapshot. snapshot: RefCell, /// Contains the state of the buffers being edited - buffers: RefCell>, - // only used by consumers using `set_excerpts_for_buffer` + buffers: HashMap, + /// Mapping from path keys to their excerpts. excerpts_by_path: BTreeMap>, + /// Mapping from excerpt IDs to their path key. paths_by_excerpt: HashMap, + /// Mapping from buffer IDs to their diff states diffs: HashMap, - // all_diff_hunks_expanded: bool, subscriptions: Topic, /// If true, the multi-buffer only contains a single [`Buffer`] and a single [`Excerpt`] singleton: bool, + /// The history of the multi-buffer. history: History, + /// The explicit title of the multi-buffer. + /// If `None`, it will be derived from the underlying path or content. title: Option, + /// The writing capability of the multi-buffer. capability: Capability, buffer_changed_since_sync: Rc>, } @@ -249,8 +254,8 @@ pub trait ToPointUtf16: 'static + fmt::Debug { struct BufferState { buffer: Entity, - last_version: clock::Global, - last_non_text_state_update_count: usize, + last_version: RefCell, + last_non_text_state_update_count: Cell, excerpts: Vec, _subscriptions: [gpui::Subscription; 2], } @@ -282,15 +287,20 @@ impl DiffState { #[derive(Clone, Default)] pub struct MultiBufferSnapshot { singleton: bool, + /* mut */ excerpts: SumTree, + /* mut */ excerpt_ids: SumTree, diffs: TreeMap, diff_transforms: SumTree, + /* mut */ replaced_excerpts: TreeMap, + /* mut */ trailing_excerpt_update_count: usize, all_diff_hunks_expanded: bool, non_text_state_update_count: usize, edit_count: usize, + /* mut */ is_dirty: bool, has_deleted_file: bool, has_conflict: bool, @@ -612,12 +622,41 @@ impl IndentGuide { impl MultiBuffer { pub fn new(capability: Capability) -> Self { - Self { - snapshot: RefCell::new(MultiBufferSnapshot { + Self::new_( + capability, + MultiBufferSnapshot { show_headers: true, ..MultiBufferSnapshot::default() - }), - buffers: RefCell::default(), + }, + ) + } + + pub fn without_headers(capability: Capability) -> Self { + Self::new_(capability, Default::default()) + } + + pub fn singleton(buffer: Entity, cx: &mut Context) -> Self { + let mut this = Self::new_( + buffer.read(cx).capability(), + MultiBufferSnapshot { + singleton: true, + ..MultiBufferSnapshot::default() + }, + ); + this.singleton = true; + this.push_excerpts( + buffer, + [ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], + cx, + ); + this + } + + #[inline] + pub fn new_(capability: Capability, snapshot: MultiBufferSnapshot) -> Self { + Self { + snapshot: RefCell::new(snapshot), + buffers: Default::default(), diffs: HashMap::default(), subscriptions: Topic::default(), singleton: false, @@ -636,32 +675,10 @@ impl MultiBuffer { } } - pub fn without_headers(capability: Capability) -> Self { - Self { - snapshot: Default::default(), - buffers: Default::default(), - excerpts_by_path: Default::default(), - paths_by_excerpt: Default::default(), - diffs: HashMap::default(), - subscriptions: Default::default(), - singleton: false, - capability, - buffer_changed_since_sync: Default::default(), - history: History { - next_transaction_id: Default::default(), - undo_stack: Default::default(), - redo_stack: Default::default(), - transaction_depth: 0, - group_interval: Duration::from_millis(300), - }, - title: Default::default(), - } - } - pub fn clone(&self, new_cx: &mut Context) -> Self { let mut buffers = HashMap::default(); let buffer_changed_since_sync = Rc::new(Cell::new(false)); - for (buffer_id, buffer_state) in self.buffers.borrow().iter() { + for (buffer_id, buffer_state) in self.buffers.iter() { buffer_state.buffer.update(new_cx, |buffer, _| { buffer.record_changes(Rc::downgrade(&buffer_changed_since_sync)); }); @@ -670,7 +687,9 @@ impl MultiBuffer { BufferState { buffer: buffer_state.buffer.clone(), last_version: buffer_state.last_version.clone(), - last_non_text_state_update_count: buffer_state.last_non_text_state_update_count, + last_non_text_state_update_count: buffer_state + .last_non_text_state_update_count + .clone(), excerpts: buffer_state.excerpts.clone(), _subscriptions: [ new_cx.observe(&buffer_state.buffer, |_, _, cx| cx.notify()), @@ -685,7 +704,7 @@ impl MultiBuffer { } Self { snapshot: RefCell::new(self.snapshot.borrow().clone()), - buffers: RefCell::new(buffers), + buffers: buffers, excerpts_by_path: Default::default(), paths_by_excerpt: Default::default(), diffs: diff_bases, @@ -707,18 +726,6 @@ impl MultiBuffer { self.capability == Capability::ReadOnly } - pub fn singleton(buffer: Entity, cx: &mut Context) -> Self { - let mut this = Self::new(buffer.read(cx).capability()); - this.singleton = true; - this.push_excerpts( - buffer, - [ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)], - cx, - ); - this.snapshot.borrow_mut().singleton = true; - this - } - /// Returns an up-to-date snapshot of the MultiBuffer. pub fn snapshot(&self, cx: &App) -> MultiBufferSnapshot { self.sync(cx); @@ -732,15 +739,7 @@ impl MultiBuffer { pub fn as_singleton(&self) -> Option> { if self.singleton { - Some( - self.buffers - .borrow() - .values() - .next() - .unwrap() - .buffer - .clone(), - ) + Some(self.buffers.values().next().unwrap().buffer.clone()) } else { None } @@ -773,7 +772,7 @@ impl MultiBuffer { } pub fn is_empty(&self) -> bool { - self.buffers.borrow().is_empty() + self.buffers.is_empty() } pub fn symbols_containing( @@ -817,7 +816,7 @@ impl MultiBuffer { mut autoindent_mode: Option, cx: &mut Context, ) { - if this.read_only() || this.buffers.borrow().is_empty() { + if this.read_only() || this.buffers.is_empty() { return; } @@ -836,78 +835,74 @@ impl MultiBuffer { for (buffer_id, mut edits) in buffer_edits { buffer_ids.push(buffer_id); edits.sort_by_key(|edit| edit.range.start); - this.buffers.borrow()[&buffer_id] - .buffer - .update(cx, |buffer, cx| { - let mut edits = edits.into_iter().peekable(); - let mut insertions = Vec::new(); - let mut original_indent_columns = Vec::new(); - let mut deletions = Vec::new(); - let empty_str: Arc = Arc::default(); + this.buffers[&buffer_id].buffer.update(cx, |buffer, cx| { + let mut edits = edits.into_iter().peekable(); + let mut insertions = Vec::new(); + let mut original_indent_columns = Vec::new(); + let mut deletions = Vec::new(); + let empty_str: Arc = Arc::default(); + while let Some(BufferEdit { + mut range, + mut new_text, + mut is_insertion, + original_indent_column, + excerpt_id, + }) = edits.next() + { while let Some(BufferEdit { - mut range, - mut new_text, - mut is_insertion, - original_indent_column, - excerpt_id, - }) = edits.next() + range: next_range, + is_insertion: next_is_insertion, + new_text: next_new_text, + excerpt_id: next_excerpt_id, + .. + }) = edits.peek() { - while let Some(BufferEdit { - range: next_range, - is_insertion: next_is_insertion, - new_text: next_new_text, - excerpt_id: next_excerpt_id, - .. - }) = edits.peek() - { - if range.end >= next_range.start { - range.end = cmp::max(next_range.end, range.end); - is_insertion |= *next_is_insertion; - if excerpt_id == *next_excerpt_id { - new_text = format!("{new_text}{next_new_text}").into(); - } - edits.next(); - } else { - break; + if range.end >= next_range.start { + range.end = cmp::max(next_range.end, range.end); + is_insertion |= *next_is_insertion; + if excerpt_id == *next_excerpt_id { + new_text = format!("{new_text}{next_new_text}").into(); } + edits.next(); + } else { + break; } + } - if is_insertion { - original_indent_columns.push(original_indent_column); - insertions.push(( - buffer.anchor_before(range.start) - ..buffer.anchor_before(range.end), - new_text.clone(), - )); - } else if !range.is_empty() { - deletions.push(( - buffer.anchor_before(range.start) - ..buffer.anchor_before(range.end), - empty_str.clone(), - )); - } + if is_insertion { + original_indent_columns.push(original_indent_column); + insertions.push(( + buffer.anchor_before(range.start)..buffer.anchor_before(range.end), + new_text.clone(), + )); + } else if !range.is_empty() { + deletions.push(( + buffer.anchor_before(range.start)..buffer.anchor_before(range.end), + empty_str.clone(), + )); } + } - let deletion_autoindent_mode = - if let Some(AutoindentMode::Block { .. }) = autoindent_mode { - Some(AutoindentMode::Block { - original_indent_columns: Default::default(), - }) - } else { - autoindent_mode.clone() - }; - let insertion_autoindent_mode = - if let Some(AutoindentMode::Block { .. }) = autoindent_mode { - Some(AutoindentMode::Block { - original_indent_columns, - }) - } else { - autoindent_mode.clone() - }; + let deletion_autoindent_mode = + if let Some(AutoindentMode::Block { .. }) = autoindent_mode { + Some(AutoindentMode::Block { + original_indent_columns: Default::default(), + }) + } else { + autoindent_mode.clone() + }; + let insertion_autoindent_mode = + if let Some(AutoindentMode::Block { .. }) = autoindent_mode { + Some(AutoindentMode::Block { + original_indent_columns, + }) + } else { + autoindent_mode.clone() + }; - buffer.edit(deletions, deletion_autoindent_mode, cx); - buffer.edit(insertions, insertion_autoindent_mode, cx); - }) + buffer.edit(deletions, deletion_autoindent_mode, cx); + buffer.edit(insertions, insertion_autoindent_mode, cx); + }) } cx.emit(Event::ExcerptsEdited { @@ -1064,7 +1059,7 @@ impl MultiBuffer { edits: Vec<(Range, Arc)>, cx: &mut Context, ) { - if this.read_only() || this.buffers.borrow().is_empty() { + if this.read_only() || this.buffers.is_empty() { return; } @@ -1088,11 +1083,9 @@ impl MultiBuffer { ranges.push(edit.range); } - this.buffers.borrow()[&buffer_id] - .buffer - .update(cx, |buffer, cx| { - buffer.autoindent_ranges(ranges, cx); - }) + this.buffers[&buffer_id].buffer.update(cx, |buffer, cx| { + buffer.autoindent_ranges(ranges, cx); + }) } cx.emit(Event::ExcerptsEdited { @@ -1135,7 +1128,7 @@ impl MultiBuffer { return buffer.update(cx, |buffer, _| buffer.start_transaction_at(now)); } - for BufferState { buffer, .. } in self.buffers.borrow().values() { + for BufferState { buffer, .. } in self.buffers.values() { buffer.update(cx, |buffer, _| buffer.start_transaction_at(now)); } self.history.start_transaction(now) @@ -1167,7 +1160,7 @@ impl MultiBuffer { } let mut buffer_transactions = HashMap::default(); - for BufferState { buffer, .. } in self.buffers.borrow().values() { + for BufferState { buffer, .. } in self.buffers.values() { if let Some(transaction_id) = buffer.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx)) { @@ -1197,11 +1190,10 @@ impl MultiBuffer { let mut ranges = Vec::new(); let snapshot = self.read(cx); - let buffers = self.buffers.borrow(); let mut cursor = snapshot.excerpts.cursor::(()); for (buffer_id, buffer_transaction) in &transaction.buffer_transactions { - let Some(buffer_state) = buffers.get(buffer_id) else { + let Some(buffer_state) = self.buffers.get(buffer_id) else { continue; }; @@ -1254,7 +1246,7 @@ impl MultiBuffer { if let Some(destination_buffer_transaction_id) = destination.buffer_transactions.get(&buffer_id) { - if let Some(state) = self.buffers.borrow().get(&buffer_id) { + if let Some(state) = self.buffers.get(&buffer_id) { state.buffer.update(cx, |buffer, _| { buffer.merge_transactions( buffer_transaction_id, @@ -1273,7 +1265,7 @@ impl MultiBuffer { pub fn finalize_last_transaction(&mut self, cx: &mut Context) { self.history.finalize_last_transaction(); - for BufferState { buffer, .. } in self.buffers.borrow().values() { + for BufferState { buffer, .. } in self.buffers.values() { buffer.update(cx, |buffer, _| { buffer.finalize_last_transaction(); }); @@ -1345,7 +1337,7 @@ impl MultiBuffer { } } - for (buffer_id, buffer_state) in self.buffers.borrow().iter() { + for (buffer_id, buffer_state) in self.buffers.iter() { if !selections_by_buffer.contains_key(buffer_id) { buffer_state .buffer @@ -1354,32 +1346,30 @@ impl MultiBuffer { } for (buffer_id, mut selections) in selections_by_buffer { - self.buffers.borrow()[&buffer_id] - .buffer - .update(cx, |buffer, cx| { - selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer)); - let mut selections = selections.into_iter().peekable(); - let merged_selections = Arc::from_iter(iter::from_fn(|| { - let mut selection = selections.next()?; - while let Some(next_selection) = selections.peek() { - if selection.end.cmp(&next_selection.start, buffer).is_ge() { - let next_selection = selections.next().unwrap(); - if next_selection.end.cmp(&selection.end, buffer).is_ge() { - selection.end = next_selection.end; - } - } else { - break; + self.buffers[&buffer_id].buffer.update(cx, |buffer, cx| { + selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer)); + let mut selections = selections.into_iter().peekable(); + let merged_selections = Arc::from_iter(iter::from_fn(|| { + let mut selection = selections.next()?; + while let Some(next_selection) = selections.peek() { + if selection.end.cmp(&next_selection.start, buffer).is_ge() { + let next_selection = selections.next().unwrap(); + if next_selection.end.cmp(&selection.end, buffer).is_ge() { + selection.end = next_selection.end; } + } else { + break; } - Some(selection) - })); - buffer.set_active_selections(merged_selections, line_mode, cursor_shape, cx); - }); + } + Some(selection) + })); + buffer.set_active_selections(merged_selections, line_mode, cursor_shape, cx); + }); } } pub fn remove_active_selections(&self, cx: &mut Context) { - for buffer in self.buffers.borrow().values() { + for buffer in self.buffers.values() { buffer .buffer .update(cx, |buffer, cx| buffer.remove_active_selections(cx)); @@ -1394,7 +1384,7 @@ impl MultiBuffer { while let Some(transaction) = self.history.pop_undo() { let mut undone = false; for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions { - if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) { + if let Some(BufferState { buffer, .. }) = self.buffers.get(buffer_id) { undone |= buffer.update(cx, |buffer, cx| { let undo_to = *buffer_transaction_id; if let Some(entry) = buffer.peek_undo_stack() { @@ -1427,7 +1417,7 @@ impl MultiBuffer { while let Some(transaction) = self.history.pop_redo() { let mut redone = false; for (buffer_id, buffer_transaction_id) in &mut transaction.buffer_transactions { - if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) { + if let Some(BufferState { buffer, .. }) = self.buffers.get(buffer_id) { redone |= buffer.update(cx, |buffer, cx| { let redo_to = *buffer_transaction_id; if let Some(entry) = buffer.peek_redo_stack() { @@ -1451,7 +1441,7 @@ impl MultiBuffer { buffer.update(cx, |buffer, cx| buffer.undo_transaction(transaction_id, cx)); } else if let Some(transaction) = self.history.remove_from_undo(transaction_id) { for (buffer_id, transaction_id) in &transaction.buffer_transactions { - if let Some(BufferState { buffer, .. }) = self.buffers.borrow().get(buffer_id) { + if let Some(BufferState { buffer, .. }) = self.buffers.get(buffer_id) { buffer.update(cx, |buffer, cx| { buffer.undo_transaction(*transaction_id, cx) }); @@ -1467,7 +1457,7 @@ impl MultiBuffer { }); } else if let Some(transaction) = self.history.forget(transaction_id) { for (buffer_id, buffer_transaction_id) in transaction.buffer_transactions { - if let Some(state) = self.buffers.borrow_mut().get_mut(&buffer_id) { + if let Some(state) = self.buffers.get_mut(&buffer_id) { state.buffer.update(cx, |buffer, _| { buffer.forget_transaction(buffer_transaction_id); }); @@ -1571,12 +1561,7 @@ impl MultiBuffer { continue; }; - let Some(buffer) = self - .buffers - .borrow() - .get(buffer_id) - .map(|b| b.buffer.clone()) - else { + let Some(buffer) = self.buffers.get(buffer_id).map(|b| b.buffer.clone()) else { continue; }; @@ -1631,13 +1616,13 @@ impl MultiBuffer { pub fn set_anchored_excerpts_for_path( &self, + path_key: PathKey, buffer: Entity, ranges: Vec>, context_line_count: u32, cx: &mut Context, ) -> Task>> { let buffer_snapshot = buffer.read(cx).snapshot(); - let path_key = PathKey::for_buffer(&buffer, cx); cx.spawn(async move |multi_buffer, cx| { let snapshot = buffer_snapshot.clone(); let (excerpt_ranges, new, counts) = cx @@ -1802,7 +1787,7 @@ impl MultiBuffer { last.context.end = last.context.end.max(existing_range.end); to_remove.push(*existing_id); self.snapshot - .borrow_mut() + .get_mut() .replaced_excerpts .insert(*existing_id, *last_id); existing_iter.next(); @@ -1852,7 +1837,7 @@ impl MultiBuffer { let existing_id = existing_iter.next().unwrap(); let new_id = next_excerpt_id(); self.snapshot - .borrow_mut() + .get_mut() .replaced_excerpts .insert(existing_id, new_id); to_remove.push(existing_id); @@ -1941,15 +1926,16 @@ impl MultiBuffer { let buffer_snapshot = buffer.read(cx).snapshot(); let buffer_id = buffer_snapshot.remote_id(); - let mut buffers = self.buffers.borrow_mut(); - let buffer_state = buffers.entry(buffer_id).or_insert_with(|| { + let buffer_state = self.buffers.entry(buffer_id).or_insert_with(|| { self.buffer_changed_since_sync.replace(true); buffer.update(cx, |buffer, _| { buffer.record_changes(Rc::downgrade(&self.buffer_changed_since_sync)); }); BufferState { - last_version: buffer_snapshot.version().clone(), - last_non_text_state_update_count: buffer_snapshot.non_text_state_update_count(), + last_version: RefCell::new(buffer_snapshot.version().clone()), + last_non_text_state_update_count: Cell::new( + buffer_snapshot.non_text_state_update_count(), + ), excerpts: Default::default(), _subscriptions: [ cx.observe(&buffer, |_, _, cx| cx.notify()), @@ -1959,7 +1945,7 @@ impl MultiBuffer { } }); - let mut snapshot = self.snapshot.borrow_mut(); + let mut snapshot = self.snapshot.get_mut(); let mut prev_locator = snapshot.excerpt_locator_for_id(prev_excerpt_id).clone(); let mut new_excerpt_ids = mem::take(&mut snapshot.excerpt_ids); @@ -2023,7 +2009,7 @@ impl MultiBuffer { snapshot.trailing_excerpt_update_count += 1; } - self.sync_diff_transforms( + let edits = Self::sync_diff_transforms( &mut snapshot, vec![Edit { old: edit_start..edit_start, @@ -2031,6 +2017,10 @@ impl MultiBuffer { }], DiffChangeKind::BufferEdited, ); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } + cx.emit(Event::Edited { edited_buffer: None, }); @@ -2045,15 +2035,10 @@ impl MultiBuffer { pub fn clear(&mut self, cx: &mut Context) { self.sync(cx); let ids = self.excerpt_ids(); - let removed_buffer_ids = self - .buffers - .borrow_mut() - .drain() - .map(|(id, _)| id) - .collect(); + let removed_buffer_ids = self.buffers.drain().map(|(id, _)| id).collect(); self.excerpts_by_path.clear(); self.paths_by_excerpt.clear(); - let mut snapshot = self.snapshot.borrow_mut(); + let mut snapshot = self.snapshot.get_mut(); let start = ExcerptOffset::new(0); let prev_len = ExcerptOffset::new(snapshot.excerpts.summary().text.len); snapshot.excerpts = Default::default(); @@ -2063,7 +2048,7 @@ impl MultiBuffer { snapshot.has_conflict = false; snapshot.replaced_excerpts.clear(); - self.sync_diff_transforms( + let edits = Self::sync_diff_transforms( &mut snapshot, vec![Edit { old: start..prev_len, @@ -2071,6 +2056,9 @@ impl MultiBuffer { }], DiffChangeKind::BufferEdited, ); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } cx.emit(Event::Edited { edited_buffer: None, }); @@ -2088,9 +2076,8 @@ impl MultiBuffer { ) -> Vec<(ExcerptId, ExcerptRange)> { let mut excerpts = Vec::new(); let snapshot = self.read(cx); - let buffers = self.buffers.borrow(); let mut cursor = snapshot.excerpts.cursor::>(()); - if let Some(locators) = buffers.get(&buffer_id).map(|state| &state.excerpts) { + if let Some(locators) = self.buffers.get(&buffer_id).map(|state| &state.excerpts) { for locator in locators { cursor.seek_forward(&Some(locator), Bias::Left); if let Some(excerpt) = cursor.item() @@ -2106,7 +2093,6 @@ impl MultiBuffer { pub fn excerpt_ranges_for_buffer(&self, buffer_id: BufferId, cx: &App) -> Vec> { let snapshot = self.read(cx); - let buffers = self.buffers.borrow(); let mut excerpts = snapshot .excerpts .cursor::, ExcerptDimension>>(()); @@ -2114,7 +2100,8 @@ impl MultiBuffer { .diff_transforms .cursor::, OutputDimension>>(()); diff_transforms.next(); - let locators = buffers + let locators = self + .buffers .get(&buffer_id) .into_iter() .flat_map(|state| &state.excerpts); @@ -2175,12 +2162,7 @@ impl MultiBuffer { .map(|excerpt| { ( excerpt.id, - self.buffers - .borrow() - .get(&excerpt.buffer_id) - .unwrap() - .buffer - .clone(), + self.buffers.get(&excerpt.buffer_id).unwrap().buffer.clone(), excerpt.range.context.clone(), ) }) @@ -2204,11 +2186,7 @@ impl MultiBuffer { let snapshot = self.read(cx); let (buffer, offset) = snapshot.point_to_buffer_offset(point)?; Some(( - self.buffers - .borrow() - .get(&buffer.remote_id())? - .buffer - .clone(), + self.buffers.get(&buffer.remote_id())?.buffer.clone(), offset, )) } @@ -2223,11 +2201,7 @@ impl MultiBuffer { let (buffer, point, is_main_buffer) = snapshot.point_to_buffer_point(point.to_point(&snapshot))?; Some(( - self.buffers - .borrow() - .get(&buffer.remote_id())? - .buffer - .clone(), + self.buffers.get(&buffer.remote_id())?.buffer.clone(), point, is_main_buffer, )) @@ -2273,8 +2247,7 @@ impl MultiBuffer { return; } - let mut buffers = self.buffers.borrow_mut(); - let mut snapshot = self.snapshot.borrow_mut(); + let mut snapshot = self.snapshot.get_mut(); let mut new_excerpts = SumTree::default(); let mut cursor = snapshot .excerpts @@ -2297,14 +2270,14 @@ impl MultiBuffer { // Skip over the removed excerpt. 'remove_excerpts: loop { - if let Some(buffer_state) = buffers.get_mut(&excerpt.buffer_id) { + if let Some(buffer_state) = self.buffers.get_mut(&excerpt.buffer_id) { buffer_state.excerpts.retain(|l| l != &excerpt.locator); if buffer_state.excerpts.is_empty() { log::debug!( "removing buffer and diff for buffer {}", excerpt.buffer_id ); - buffers.remove(&excerpt.buffer_id); + self.buffers.remove(&excerpt.buffer_id); removed_buffer_ids.push(excerpt.buffer_id); } } @@ -2355,7 +2328,10 @@ impl MultiBuffer { snapshot.trailing_excerpt_update_count += 1; } - self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } self.buffer_changed_since_sync.replace(true); cx.emit(Event::Edited { edited_buffer: None, @@ -2372,12 +2348,11 @@ impl MultiBuffer { anchors: Anchors, cx: &mut Context, ) -> impl 'static + Future> + use { - let borrow = self.buffers.borrow(); let mut error = None; let mut futures = Vec::new(); for anchor in anchors { if let Some(buffer_id) = anchor.buffer_id { - if let Some(buffer) = borrow.get(&buffer_id) { + if let Some(buffer) = self.buffers.get(&buffer_id) { buffer.buffer.update(cx, |buffer, _| { futures.push(buffer.wait_for_anchors([anchor.text_anchor])) }); @@ -2407,12 +2382,7 @@ impl MultiBuffer { ) -> Option<(Entity, language::Anchor)> { let snapshot = self.read(cx); let anchor = snapshot.anchor_before(position); - let buffer = self - .buffers - .borrow() - .get(&anchor.buffer_id?)? - .buffer - .clone(); + let buffer = self.buffers.get(&anchor.buffer_id?)?.buffer.clone(); Some((buffer, anchor.text_anchor)) } @@ -2444,7 +2414,7 @@ impl MultiBuffer { fn buffer_diff_language_changed(&mut self, diff: Entity, cx: &mut Context) { self.sync(cx); - let mut snapshot = self.snapshot.borrow_mut(); + let snapshot = self.snapshot.get_mut(); let diff = diff.read(cx); let buffer_id = diff.buffer_id; let diff = diff.snapshot(cx); @@ -2462,8 +2432,7 @@ impl MultiBuffer { let diff = diff.read(cx); let buffer_id = diff.buffer_id; - let buffers = self.buffers.borrow(); - let Some(buffer_state) = buffers.get(&buffer_id) else { + let Some(buffer_state) = self.buffers.get(&buffer_id) else { return; }; @@ -2471,7 +2440,7 @@ impl MultiBuffer { let diff_change_range = range.to_offset(buffer); let new_diff = diff.snapshot(cx); - let mut snapshot = self.snapshot.borrow_mut(); + let mut snapshot = self.snapshot.get_mut(); let base_text_changed = snapshot .diffs .get(&buffer_id) @@ -2515,13 +2484,16 @@ impl MultiBuffer { } } - self.sync_diff_transforms( + let edits = Self::sync_diff_transforms( &mut snapshot, excerpt_edits, DiffChangeKind::DiffUpdated { base_changed: base_text_changed, }, ); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } cx.emit(Event::Edited { edited_buffer: None, }); @@ -2529,19 +2501,17 @@ impl MultiBuffer { pub fn all_buffers(&self) -> HashSet> { self.buffers - .borrow() .values() .map(|state| state.buffer.clone()) .collect() } pub fn all_buffer_ids(&self) -> Vec { - self.buffers.borrow().keys().copied().collect() + self.buffers.keys().copied().collect() } pub fn buffer(&self, buffer_id: BufferId) -> Option> { self.buffers - .borrow() .get(&buffer_id) .map(|state| state.buffer.clone()) } @@ -2583,10 +2553,7 @@ impl MultiBuffer { } pub fn for_each_buffer(&self, mut f: impl FnMut(&Entity)) { - self.buffers - .borrow() - .values() - .for_each(|state| f(&state.buffer)) + self.buffers.values().for_each(|state| f(&state.buffer)) } pub fn title<'a>(&'a self, cx: &'a App) -> Cow<'a, str> { @@ -2655,7 +2622,7 @@ impl MultiBuffer { /// Preserve preview tabs containing this multibuffer until additional edits occur. pub fn refresh_preview(&self, cx: &mut Context) { - for buffer_state in self.buffers.borrow().values() { + for buffer_state in self.buffers.values() { buffer_state .buffer .update(cx, |buffer, _cx| buffer.refresh_preview()); @@ -2665,7 +2632,6 @@ impl MultiBuffer { /// Whether we should preserve the preview status of a tab containing this multi-buffer. pub fn preserve_preview(&self, cx: &App) -> bool { self.buffers - .borrow() .values() .all(|state| state.buffer.read(cx).preserve_preview()) } @@ -2694,7 +2660,7 @@ impl MultiBuffer { } pub fn set_all_diff_hunks_expanded(&mut self, cx: &mut Context) { - self.snapshot.borrow_mut().all_diff_hunks_expanded = true; + self.snapshot.get_mut().all_diff_hunks_expanded = true; self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], true, cx); } @@ -2703,7 +2669,7 @@ impl MultiBuffer { } pub fn set_all_diff_hunks_collapsed(&mut self, cx: &mut Context) { - self.snapshot.borrow_mut().all_diff_hunks_expanded = false; + self.snapshot.get_mut().all_diff_hunks_expanded = false; self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], false, cx); } @@ -2764,7 +2730,7 @@ impl MultiBuffer { return; } self.sync(cx); - let mut snapshot = self.snapshot.borrow_mut(); + let mut snapshot = self.snapshot.get_mut(); let mut excerpt_edits = Vec::new(); let mut last_hunk_row = None; for (range, end_excerpt_id) in ranges { @@ -2795,11 +2761,14 @@ impl MultiBuffer { } } - self.sync_diff_transforms( + let edits = Self::sync_diff_transforms( &mut snapshot, excerpt_edits, DiffChangeKind::ExpandOrCollapseHunks { expand }, ); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } cx.emit(Event::DiffHunksToggled); cx.emit(Event::Edited { edited_buffer: None, @@ -2833,7 +2802,7 @@ impl MultiBuffer { ) { self.sync(cx); - let mut snapshot = self.snapshot.borrow_mut(); + let mut snapshot = self.snapshot.get_mut(); let locator = snapshot.excerpt_locator_for_id(id); let mut new_excerpts = SumTree::default(); let mut cursor = snapshot @@ -2883,7 +2852,10 @@ impl MultiBuffer { drop(cursor); snapshot.excerpts = new_excerpts; - self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } cx.emit(Event::Edited { edited_buffer: None, }); @@ -2906,7 +2878,7 @@ impl MultiBuffer { self.expand_excerpts_with_paths(ids, line_count, direction, cx); return; } - let mut snapshot = self.snapshot.borrow_mut(); + let mut snapshot = self.snapshot.get_mut(); let ids = ids.into_iter().collect::>(); let locators = snapshot.excerpt_locators_for_ids(ids.iter().copied()); @@ -2987,7 +2959,10 @@ impl MultiBuffer { drop(cursor); snapshot.excerpts = new_excerpts; - self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } cx.emit(Event::Edited { edited_buffer: None, }); @@ -3008,18 +2983,19 @@ impl MultiBuffer { let mut has_deleted_file = false; let mut has_conflict = false; let mut edited = false; - let mut buffers = self.buffers.borrow_mut(); - for buffer_state in buffers.values_mut() { + for buffer_state in self.buffers.values() { let buffer = buffer_state.buffer.read(cx); let version = buffer.version(); let non_text_state_update_count = buffer.non_text_state_update_count(); - let buffer_edited = version.changed_since(&buffer_state.last_version); + let buffer_edited = version.changed_since(&buffer_state.last_version.borrow()); let buffer_non_text_state_updated = - non_text_state_update_count > buffer_state.last_non_text_state_update_count; + non_text_state_update_count > buffer_state.last_non_text_state_update_count.get(); if buffer_edited || buffer_non_text_state_updated { - buffer_state.last_version = version; - buffer_state.last_non_text_state_update_count = non_text_state_update_count; + *buffer_state.last_version.borrow_mut() = version; + buffer_state + .last_non_text_state_update_count + .set(non_text_state_update_count); excerpts_to_edit.extend( buffer_state .excerpts @@ -3110,17 +3086,19 @@ impl MultiBuffer { drop(cursor); snapshot.excerpts = new_excerpts; - self.sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + let edits = Self::sync_diff_transforms(&mut snapshot, edits, DiffChangeKind::BufferEdited); + if !edits.is_empty() { + self.subscriptions.publish(edits); + } } fn sync_diff_transforms( - &self, snapshot: &mut MultiBufferSnapshot, excerpt_edits: Vec>, change_kind: DiffChangeKind, - ) { + ) -> Vec> { if excerpt_edits.is_empty() { - return; + return vec![]; } let mut excerpts = snapshot.excerpts.cursor::(()); @@ -3145,12 +3123,12 @@ impl MultiBuffer { if at_transform_boundary { at_transform_boundary = false; let transforms_before_edit = old_diff_transforms.slice(&edit.old.start, Bias::Left); - self.append_diff_transforms(&mut new_diff_transforms, transforms_before_edit); + Self::append_diff_transforms(&mut new_diff_transforms, transforms_before_edit); if let Some(transform) = old_diff_transforms.item() && old_diff_transforms.end().0 == edit.old.start && old_diff_transforms.start().0 < edit.old.start { - self.push_diff_transform(&mut new_diff_transforms, transform.clone()); + Self::push_diff_transform(&mut new_diff_transforms, transform.clone()); old_diff_transforms.next(); } } @@ -3160,7 +3138,7 @@ impl MultiBuffer { let edit_old_start = old_diff_transforms.start().1 + edit_start_overshoot; let edit_new_start = (edit_old_start as isize + output_delta) as usize; - let changed_diff_hunks = self.recompute_diff_transforms_for_edit( + let changed_diff_hunks = Self::recompute_diff_transforms_for_edit( &edit, &mut excerpts, &mut old_diff_transforms, @@ -3213,7 +3191,7 @@ impl MultiBuffer { } old_expanded_hunks.clear(); - self.push_buffer_content_transform( + Self::push_buffer_content_transform( snapshot, &mut new_diff_transforms, excerpt_offset, @@ -3224,7 +3202,7 @@ impl MultiBuffer { } // Keep any transforms that are after the last edit. - self.append_diff_transforms(&mut new_diff_transforms, old_diff_transforms.suffix()); + Self::append_diff_transforms(&mut new_diff_transforms, old_diff_transforms.suffix()); // Ensure there's always at least one buffer content transform. if new_diff_transforms.is_empty() { @@ -3237,7 +3215,6 @@ impl MultiBuffer { ); } - self.subscriptions.publish(output_edits); drop(old_diff_transforms); drop(excerpts); snapshot.diff_transforms = new_diff_transforms; @@ -3245,10 +3222,10 @@ impl MultiBuffer { #[cfg(any(test, feature = "test-support"))] snapshot.check_invariants(); + output_edits } fn recompute_diff_transforms_for_edit( - &self, edit: &Edit>, excerpts: &mut Cursor>, old_diff_transforms: &mut Cursor, usize>>, @@ -3333,7 +3310,7 @@ impl MultiBuffer { + ExcerptOffset::new(hunk_buffer_range.end - excerpt_buffer_start), ); - self.push_buffer_content_transform( + Self::push_buffer_content_transform( snapshot, new_diff_transforms, hunk_excerpt_start, @@ -3414,7 +3391,6 @@ impl MultiBuffer { } fn append_diff_transforms( - &self, new_transforms: &mut SumTree, subtree: SumTree, ) { @@ -3422,7 +3398,7 @@ impl MultiBuffer { inserted_hunk_info, summary, }) = subtree.first() - && self.extend_last_buffer_content_transform( + && Self::extend_last_buffer_content_transform( new_transforms, *inserted_hunk_info, *summary, @@ -3437,16 +3413,12 @@ impl MultiBuffer { new_transforms.append(subtree, ()); } - fn push_diff_transform( - &self, - new_transforms: &mut SumTree, - transform: DiffTransform, - ) { + fn push_diff_transform(new_transforms: &mut SumTree, transform: DiffTransform) { if let DiffTransform::BufferContent { inserted_hunk_info: inserted_hunk_anchor, summary, } = transform - && self.extend_last_buffer_content_transform( + && Self::extend_last_buffer_content_transform( new_transforms, inserted_hunk_anchor, summary, @@ -3458,7 +3430,6 @@ impl MultiBuffer { } fn push_buffer_content_transform( - &self, old_snapshot: &MultiBufferSnapshot, new_transforms: &mut SumTree, end_offset: ExcerptOffset, @@ -3478,7 +3449,7 @@ impl MultiBuffer { let summary_to_add = old_snapshot .text_summary_for_excerpt_offset_range::(start_offset..end_offset); - if !self.extend_last_buffer_content_transform( + if !Self::extend_last_buffer_content_transform( new_transforms, inserted_hunk_info, summary_to_add, @@ -3495,7 +3466,6 @@ impl MultiBuffer { } fn extend_last_buffer_content_transform( - &self, new_transforms: &mut SumTree, new_inserted_hunk_info: Option, summary_to_add: TextSummary, @@ -3655,7 +3625,7 @@ impl MultiBuffer { let excerpt_ids = self.excerpt_ids(); if excerpt_ids.is_empty() || (rng.random() && excerpt_ids.len() < max_excerpts) { - let buffer_handle = if rng.random() || self.buffers.borrow().is_empty() { + let buffer_handle = if rng.random() || self.buffers.is_empty() { let text = RandomCharIter::new(&mut *rng).take(10).collect::(); buffers.push(cx.new(|cx| Buffer::local(text, cx))); let buffer = buffers.last().unwrap().read(cx); @@ -3666,13 +3636,7 @@ impl MultiBuffer { ); buffers.last().unwrap().clone() } else { - self.buffers - .borrow() - .values() - .choose(rng) - .unwrap() - .buffer - .clone() + self.buffers.values().choose(rng).unwrap().buffer.clone() }; let buffer = buffer_handle.read(cx); @@ -3723,7 +3687,6 @@ impl MultiBuffer { if rng.random_bool(0.7) || self.singleton { let buffer = self .buffers - .borrow() .values() .choose(rng) .map(|state| state.buffer.clone()); diff --git a/crates/multi_buffer/src/multi_buffer_tests.rs b/crates/multi_buffer/src/multi_buffer_tests.rs index 2f4bfdfda8d023cf08e31ec6ffc9300446f8a400..1532e5b68ec29e6befbbd17fa97b966449874822 100644 --- a/crates/multi_buffer/src/multi_buffer_tests.rs +++ b/crates/multi_buffer/src/multi_buffer_tests.rs @@ -797,7 +797,13 @@ async fn test_set_anchored_excerpts_for_path(cx: &mut TestAppContext) { let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite)); let anchor_ranges_1 = multibuffer .update(cx, |multibuffer, cx| { - multibuffer.set_anchored_excerpts_for_path(buffer_1.clone(), ranges_1, 2, cx) + multibuffer.set_anchored_excerpts_for_path( + PathKey::for_buffer(&buffer_1, cx), + buffer_1.clone(), + ranges_1, + 2, + cx, + ) }) .await; let snapshot_1 = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx)); @@ -814,7 +820,13 @@ async fn test_set_anchored_excerpts_for_path(cx: &mut TestAppContext) { ); let anchor_ranges_2 = multibuffer .update(cx, |multibuffer, cx| { - multibuffer.set_anchored_excerpts_for_path(buffer_2.clone(), ranges_2, 2, cx) + multibuffer.set_anchored_excerpts_for_path( + PathKey::for_buffer(&buffer_2, cx), + buffer_2.clone(), + ranges_2, + 2, + cx, + ) }) .await; let snapshot_2 = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx)); diff --git a/crates/project/src/git_store/conflict_set.rs b/crates/project/src/git_store/conflict_set.rs index 13a082b35024b11870fb14fb3419c76841566193..879280c885a0bfda20e5faa70e1e07f7d9fe038c 100644 --- a/crates/project/src/git_store/conflict_set.rs +++ b/crates/project/src/git_store/conflict_set.rs @@ -72,13 +72,15 @@ impl ConflictSetSnapshot { (None, None) => None, (None, Some(conflict)) => Some(conflict.range.start), (Some(conflict), None) => Some(conflict.range.start), - (Some(first), Some(second)) => Some(first.range.start.min(&second.range.start, buffer)), + (Some(first), Some(second)) => { + Some(*first.range.start.min(&second.range.start, buffer)) + } }; let end = match (old_conflicts.last(), new_conflicts.last()) { (None, None) => None, (None, Some(conflict)) => Some(conflict.range.end), (Some(first), None) => Some(first.range.end), - (Some(first), Some(second)) => Some(first.range.end.max(&second.range.end, buffer)), + (Some(first), Some(second)) => Some(*first.range.end.max(&second.range.end, buffer)), }; ConflictSetUpdate { buffer_range: start.zip(end).map(|(start, end)| start..end), diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 4197e57e4d4db0f3ca6d3827d5b32ba19fab6295..1373c7d8454c9e31681d8365f167026f666cb429 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -8,7 +8,8 @@ use crate::{ use anyhow::Context as _; use collections::HashMap; use editor::{ - Anchor, Editor, EditorEvent, EditorSettings, MAX_TAB_TITLE_LEN, MultiBuffer, SelectionEffects, + Anchor, Editor, EditorEvent, EditorSettings, MAX_TAB_TITLE_LEN, MultiBuffer, PathKey, + SelectionEffects, actions::{Backtab, SelectAll, Tab}, items::active_match_index, multibuffer_context_lines, @@ -340,6 +341,7 @@ impl ProjectSearch { .into_iter() .map(|(buffer, ranges)| { excerpts.set_anchored_excerpts_for_path( + PathKey::for_buffer(&buffer, cx), buffer, ranges, multibuffer_context_lines(cx), diff --git a/crates/text/src/anchor.rs b/crates/text/src/anchor.rs index a05da1243faa05f33708fe6858fc9dada3c0a1e0..56172c21afcf9fa70a9039218feea59f055a27c5 100644 --- a/crates/text/src/anchor.rs +++ b/crates/text/src/anchor.rs @@ -45,19 +45,19 @@ impl Anchor { .then_with(|| self.bias.cmp(&other.bias)) } - pub fn min(&self, other: &Self, buffer: &BufferSnapshot) -> Self { + pub fn min<'a>(&'a self, other: &'a Self, buffer: &BufferSnapshot) -> &'a Self { if self.cmp(other, buffer).is_le() { - *self + self } else { - *other + other } } - pub fn max(&self, other: &Self, buffer: &BufferSnapshot) -> Self { + pub fn max<'a>(&'a self, other: &'a Self, buffer: &BufferSnapshot) -> &'a Self { if self.cmp(other, buffer).is_ge() { - *self + self } else { - *other + other } }