diff --git a/Cargo.lock b/Cargo.lock index 78166ddc04990b2998e2a64cf831f415efd7ed61..77ccfe789f121f9358acc79507f4d6419b37ed20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17998,6 +17998,7 @@ name = "title_bar" version = "0.1.0" dependencies = [ "anyhow", + "arrayvec", "auto_update", "call", "channel", diff --git a/crates/csv_preview/src/renderer/table_cell.rs b/crates/csv_preview/src/renderer/table_cell.rs index 733488110fbcdb39761b150a74c135426ca6514a..cc9690b4233c2f3b3150ff48df9e710ac7b870d2 100644 --- a/crates/csv_preview/src/renderer/table_cell.rs +++ b/crates/csv_preview/src/renderer/table_cell.rs @@ -39,13 +39,12 @@ fn create_table_cell( cx: &Context<'_, CsvPreviewView>, ) -> gpui::Stateful
{ div() - .id(ElementId::NamedInteger( + .id(ElementId::Name( format!( "csv-display-cell-{}-{}", *display_cell_id.row, *display_cell_id.col ) .into(), - 0, )) .cursor_pointer() .flex() diff --git a/crates/edit_prediction_context/src/edit_prediction_context.rs b/crates/edit_prediction_context/src/edit_prediction_context.rs index a44ff8b2e3e873c23c2eaa914298a4d50aee3bdc..261d3383d0a4a4985a1b45891015bf1e1738b8a9 100644 --- a/crates/edit_prediction_context/src/edit_prediction_context.rs +++ b/crates/edit_prediction_context/src/edit_prediction_context.rs @@ -66,10 +66,14 @@ struct Identifier { enum DefinitionTask { CacheHit(Arc), - CacheMiss { - definitions: Task>>>, - type_definitions: Task>>>, - }, + CacheMiss( + Task< + Option<( + Task>>>, + Task>>>, + )>, + >, + ), } #[derive(Debug)] @@ -270,39 +274,37 @@ impl RelatedExcerptStore { let futures = this.update(cx, |this, cx| { identifiers_with_distance .into_iter() - .filter_map(|(identifier, _)| { + .map(|(identifier, _)| { let task = if let Some(entry) = this.cache.get(&identifier) { DefinitionTask::CacheHit(entry.clone()) } else { - let definitions = this - .project - .update(cx, |project, cx| { - project.definitions(&buffer, identifier.range.start, cx) - }) - .ok()?; - let type_definitions = this - .project - .update(cx, |project, cx| { - project.type_definitions(&buffer, identifier.range.start, cx) - }) - .ok()?; - DefinitionTask::CacheMiss { - definitions, - type_definitions, - } + let project = this.project.clone(); + let buffer = buffer.downgrade(); + DefinitionTask::CacheMiss(cx.spawn(async move |_, cx| { + let buffer = buffer.upgrade()?; + let definitions = project + .update(cx, |project, cx| { + project.definitions(&buffer, identifier.range.start, cx) + }) + .ok()?; + let type_definitions = project + .update(cx, |project, cx| { + project.type_definitions(&buffer, identifier.range.start, cx) + }) + .ok()?; + Some((definitions, type_definitions)) + })) }; let cx = async_cx.clone(); let project = project.clone(); - Some(async move { + async move { match task { DefinitionTask::CacheHit(cache_entry) => { Some((identifier, cache_entry, None)) } - DefinitionTask::CacheMiss { - definitions, - type_definitions, - } => { + DefinitionTask::CacheMiss(task) => { + let (definitions, type_definitions) = task.await?; let (definition_locations, type_definition_locations) = futures::join!(definitions, type_definitions); let duration = start_time.elapsed(); @@ -349,7 +351,7 @@ impl RelatedExcerptStore { })) } } - }) + } }) .collect::>() })?; diff --git a/crates/editor/src/semantic_tokens.rs b/crates/editor/src/semantic_tokens.rs index eaadbbb0e2ee9a49e53cc645487ea489572b1241..29c998ce976fee988e027db64ebd1f35f709f0af 100644 --- a/crates/editor/src/semantic_tokens.rs +++ b/crates/editor/src/semantic_tokens.rs @@ -15,7 +15,7 @@ use project::{ project_settings::ProjectSettings, }; use settings::{ - SemanticTokenColorOverride, SemanticTokenFontStyle, SemanticTokenFontWeight, + SemanticTokenColorOverride, SemanticTokenFontStyle, SemanticTokenFontWeight, SemanticTokenRule, SemanticTokenRules, Settings as _, }; use text::BufferId; @@ -295,13 +295,14 @@ impl Editor { ) else { continue; }; + let theme = cx.theme().syntax(); token_highlights.reserve(2 * server_tokens.len()); token_highlights.extend(buffer_into_editor_highlights( &server_tokens, stylizer, &multi_buffer_snapshot, &mut interner, - cx, + theme, )); } @@ -328,7 +329,7 @@ fn buffer_into_editor_highlights<'a, 'b>( stylizer: &'a SemanticTokenStylizer, multi_buffer_snapshot: &'a multi_buffer::MultiBufferSnapshot, interner: &'b mut HighlightStyleInterner, - cx: &'a App, + theme: &'a SyntaxTheme, ) -> impl Iterator + use<'a, 'b> { multi_buffer_snapshot .text_anchors_to_visible_anchors( @@ -341,12 +342,7 @@ fn buffer_into_editor_highlights<'a, 'b>( .zip(buffer_tokens) .filter_map(|((multi_buffer_start, multi_buffer_end), token)| { let range = multi_buffer_start?..multi_buffer_end?; - let style = convert_token( - stylizer, - cx.theme().syntax(), - token.token_type, - token.token_modifiers, - )?; + let style = convert_token(stylizer, theme, token.token_type, token.token_modifiers)?; let style = interner.intern(style); Some(SemanticTokenHighlight { range, @@ -365,27 +361,19 @@ fn convert_token( modifiers: u32, ) -> Option { let rules = stylizer.rules_for_token(token_type)?; - let matching: Vec<_> = rules - .iter() - .filter(|rule| { - rule.token_modifiers - .iter() - .all(|m| stylizer.has_modifier(modifiers, m)) - }) - .collect(); - - if let Some(rule) = matching.last() { - if rule.no_style_defined() { - return None; - } + let filter = |rule: &&SemanticTokenRule| { + rule.token_modifiers + .iter() + .all(|m| stylizer.has_modifier(modifiers, m)) + }; + let last = rules.last()?; + if last.no_style_defined() && filter(&last) { + return None; } let mut highlight = HighlightStyle::default(); - let mut empty = true; - - for rule in matching { - empty = false; + for rule in rules.into_iter().filter(filter) { let style = rule .style .iter() @@ -400,7 +388,7 @@ fn convert_token( highlight.$highlight_field = rule .$rule_field .map($transform) - .or_else(|| style.and_then(|s| s.$highlight_field)) + .or_else(|| style.as_ref().and_then(|s| s.$highlight_field)) .or(highlight.$highlight_field) }; } @@ -460,8 +448,7 @@ fn convert_token( }, ); } - - if empty { None } else { Some(highlight) } + Some(highlight) } #[cfg(test)] diff --git a/crates/gpui/src/bounds_tree.rs b/crates/gpui/src/bounds_tree.rs index 9cf86a2cc9b6def8fbf5ca7e94f7cd19236468cc..e95e32477b912b810607b20306be5f7d53c76df2 100644 --- a/crates/gpui/src/bounds_tree.rs +++ b/crates/gpui/src/bounds_tree.rs @@ -3,6 +3,7 @@ use std::{ cmp, fmt::Debug, ops::{Add, Sub}, + ptr::NonNull, }; /// Maximum children per internal node (R-tree style branching factor). @@ -30,7 +31,7 @@ where /// Reusable stack for tree traversal during insertion. insert_path: Vec, /// Reusable stack for search operations. - search_stack: Vec, + search_stack: Vec>>, } /// A node in the bounds tree. @@ -150,12 +151,14 @@ where // Slow path: search the tree self.search_stack.clear(); - self.search_stack.push(root_idx); + self.search_stack.push(NonNull::from(&self.nodes[root_idx])); let mut max_found = 0u32; - while let Some(node_idx) = self.search_stack.pop() { - let node = &self.nodes[node_idx]; + while let Some(node) = self.search_stack.pop() { + // SAFETY: `node` is guaranteed to be valid as the `nodes` stack is unmodified in this function + // and the `search_stack` only contains pointers from this function call. + let node = unsafe { node.as_ref() }; // Pruning: skip if this subtree can't improve our result if node.max_order <= max_found { @@ -174,11 +177,14 @@ where NodeKind::Internal { children } => { // Children are maintained with highest max_order at the end. // Push in forward order to highest (last) is popped first. - for &child_idx in children.as_slice() { - if self.nodes[child_idx].max_order > max_found { - self.search_stack.push(child_idx); - } - } + self.search_stack.extend( + children + .as_slice() + .iter() + .map(|&child_idx| &self.nodes[child_idx]) + .filter(|node| node.max_order > max_found) + .map(NonNull::from), + ); } } } diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 8fea468705eaf7950f41e47064e1962df2db8790..b9a3ce8e6a25cb77c80b711796704b6c37985132 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -1048,7 +1048,7 @@ impl AtlasTextureList { } } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[repr(C)] #[expect(missing_docs)] pub struct AtlasTile { diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index 583450c9e93e6bfdf8f45a4dcd1a83feb9b08111..ac98027b52013cb963b509f5dbbcdc29a64b44de 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/crates/gpui/src/platform/test/window.rs @@ -353,8 +353,8 @@ impl PlatformAtlas for TestAtlas { >, ) -> anyhow::Result> { let mut state = self.0.lock(); - if let Some(tile) = state.tiles.get(key) { - return Ok(Some(tile.clone())); + if let Some(&tile) = state.tiles.get(key) { + return Ok(Some(tile)); } drop(state); @@ -384,7 +384,7 @@ impl PlatformAtlas for TestAtlas { }, ); - Ok(Some(state.tiles[key].clone())) + Ok(Some(state.tiles[key])) } fn remove(&self, key: &AtlasKey) { diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index 22b1bb468d84b2897b312c6fc8af00ee5c8523db..ef37caa7b95cfbca42fdbddfed56196c33e82eee 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -88,11 +88,11 @@ impl Scene { match &mut primitive { Primitive::Shadow(shadow) => { shadow.order = order; - self.shadows.push(shadow.clone()); + self.shadows.push(*shadow); } Primitive::Quad(quad) => { quad.order = order; - self.quads.push(quad.clone()); + self.quads.push(*quad); } Primitive::Path(path) => { path.order = order; @@ -101,19 +101,19 @@ impl Scene { } Primitive::Underline(underline) => { underline.order = order; - self.underlines.push(underline.clone()); + self.underlines.push(*underline); } Primitive::MonochromeSprite(sprite) => { sprite.order = order; - self.monochrome_sprites.push(sprite.clone()); + self.monochrome_sprites.push(*sprite); } Primitive::SubpixelSprite(sprite) => { sprite.order = order; - self.subpixel_sprites.push(sprite.clone()); + self.subpixel_sprites.push(*sprite); } Primitive::PolychromeSprite(sprite) => { sprite.order = order; - self.polychrome_sprites.push(sprite.clone()); + self.polychrome_sprites.push(*sprite); } Primitive::Surface(surface) => { surface.order = order; @@ -481,7 +481,7 @@ pub enum PrimitiveBatch { Surfaces(Range), } -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Copy, Clone)] #[repr(C)] #[expect(missing_docs)] pub struct Quad { @@ -501,7 +501,7 @@ impl From for Primitive { } } -#[derive(Debug, Clone)] +#[derive(Debug, Copy, Clone)] #[repr(C)] #[expect(missing_docs)] pub struct Underline { @@ -520,7 +520,7 @@ impl From for Primitive { } } -#[derive(Debug, Clone)] +#[derive(Debug, Copy, Clone)] #[repr(C)] #[expect(missing_docs)] pub struct Shadow { @@ -652,7 +652,7 @@ impl Default for TransformationMatrix { } } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] #[expect(missing_docs)] pub struct MonochromeSprite { @@ -671,7 +671,7 @@ impl From for Primitive { } } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] #[expect(missing_docs)] pub struct SubpixelSprite { @@ -690,7 +690,7 @@ impl From for Primitive { } } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] #[expect(missing_docs)] pub struct PolychromeSprite { diff --git a/crates/gpui/src/text_system/line_layout.rs b/crates/gpui/src/text_system/line_layout.rs index 8f3d7563d068979defa8b3f93367a2c9b7102cc1..633474f2b194e18e6484b907940b6988dc5951ba 100644 --- a/crates/gpui/src/text_system/line_layout.rs +++ b/crates/gpui/src/text_system/line_layout.rs @@ -186,7 +186,7 @@ impl LineLayout { if width > wrap_width && boundary > last_boundary { // When used line_clamp, we should limit the number of lines. if let Some(max_lines) = max_lines - && boundaries.len() >= max_lines - 1 + && boundaries.len() >= max_lines.saturating_sub(1) { break; } diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index f73a59358c3b06b187fd7357b5351f557d2fd68c..ab195c629492bf26bc55f4953bc8b8c28579b0c0 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -1627,7 +1627,7 @@ pub struct DispatchEventResult { /// Indicates which region of the window is visible. Content falling outside of this mask will not be /// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type /// to leave room to support more complex shapes in the future. -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] #[repr(C)] pub struct ContentMask { /// The bounds @@ -2713,7 +2713,7 @@ impl Window { .set_active_node(deferred_draw.parent_node); let paint_start = self.paint_index(); - let content_mask = deferred_draw.content_mask.clone(); + let content_mask = deferred_draw.content_mask; if let Some(element) = deferred_draw.element.as_mut() { self.with_rendered_view(deferred_draw.current_view, |window| { window.with_content_mask(content_mask, |window| { @@ -2790,7 +2790,7 @@ impl Window { parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node), element_id_stack: deferred_draw.element_id_stack.clone(), text_style_stack: deferred_draw.text_style_stack.clone(), - content_mask: deferred_draw.content_mask.clone(), + content_mask: deferred_draw.content_mask, rem_size: deferred_draw.rem_size, priority: deferred_draw.priority, element: None, diff --git a/crates/gpui_macos/src/metal_atlas.rs b/crates/gpui_macos/src/metal_atlas.rs index e6b8443c520e1b47006104085fdc26a5415d85f6..5bedf9df8cd6f16822011faa558e1b895aae71c5 100644 --- a/crates/gpui_macos/src/metal_atlas.rs +++ b/crates/gpui_macos/src/metal_atlas.rs @@ -44,7 +44,7 @@ impl PlatformAtlas for MetalAtlas { ) -> Result> { let mut lock = self.0.lock(); if let Some(tile) = lock.tiles_by_key.get(key) { - Ok(Some(tile.clone())) + Ok(Some(*tile)) } else { let Some((size, bytes)) = build()? else { return Ok(None); @@ -54,7 +54,7 @@ impl PlatformAtlas for MetalAtlas { .context("failed to allocate")?; let texture = lock.texture(tile.texture_id); texture.upload(tile.bounds, &bytes); - lock.tiles_by_key.insert(key.clone(), tile.clone()); + lock.tiles_by_key.insert(key.clone(), tile); Ok(Some(tile)) } } diff --git a/crates/gpui_macos/src/metal_renderer.rs b/crates/gpui_macos/src/metal_renderer.rs index e96d14b15691bec1da54aa9d46e3e765218292b2..73b53ce6ea5d7e623a98ca924613d6c9bfc0ed4d 100644 --- a/crates/gpui_macos/src/metal_renderer.rs +++ b/crates/gpui_macos/src/metal_renderer.rs @@ -1469,7 +1469,7 @@ impl MetalRenderer { buffer_contents, SurfaceBounds { bounds: surface.bounds, - content_mask: surface.content_mask.clone(), + content_mask: surface.content_mask, }, ); } diff --git a/crates/gpui_shared_string/gpui_shared_string.rs b/crates/gpui_shared_string/gpui_shared_string.rs index 4fd2f8c32112feb0199408825355f60d6554e19c..79e6dcd5627decba47793aae5a9219144da3b2f1 100644 --- a/crates/gpui_shared_string/gpui_shared_string.rs +++ b/crates/gpui_shared_string/gpui_shared_string.rs @@ -46,7 +46,7 @@ impl JsonSchema for SharedString { impl Default for SharedString { fn default() -> Self { - Self(ArcCow::Owned(Arc::default())) + Self(ArcCow::Borrowed("")) } } diff --git a/crates/gpui_wgpu/src/wgpu_atlas.rs b/crates/gpui_wgpu/src/wgpu_atlas.rs index 4c2c6ab601442fbebabd6759c5111d5e852b509f..bef69878adafb71d47a1cbe222fc1454169b8c3b 100644 --- a/crates/gpui_wgpu/src/wgpu_atlas.rs +++ b/crates/gpui_wgpu/src/wgpu_atlas.rs @@ -103,7 +103,7 @@ impl PlatformAtlas for WgpuAtlas { ) -> Result> { let mut lock = self.0.lock(); if let Some(tile) = lock.tiles_by_key.get(key) { - Ok(Some(tile.clone())) + Ok(Some(*tile)) } else { profiling::scope!("new tile"); let Some((size, bytes)) = build()? else { @@ -113,7 +113,7 @@ impl PlatformAtlas for WgpuAtlas { .allocate(size, key.texture_kind()) .context("failed to allocate")?; lock.upload_texture(tile.texture_id, tile.bounds, &bytes); - lock.tiles_by_key.insert(key.clone(), tile.clone()); + lock.tiles_by_key.insert(key.clone(), tile); Ok(Some(tile)) } } diff --git a/crates/gpui_windows/src/directx_atlas.rs b/crates/gpui_windows/src/directx_atlas.rs index 03acadb8607ed3e7d957e7faa73960724fa09888..a6642dc7dc6292395891abcc250eff8b5c424524 100644 --- a/crates/gpui_windows/src/directx_atlas.rs +++ b/crates/gpui_windows/src/directx_atlas.rs @@ -80,7 +80,7 @@ impl PlatformAtlas for DirectXAtlas { ) -> anyhow::Result> { let mut lock = self.0.lock(); if let Some(tile) = lock.tiles_by_key.get(key) { - Ok(Some(tile.clone())) + Ok(Some(*tile)) } else { let Some((size, bytes)) = build()? else { return Ok(None); @@ -90,7 +90,7 @@ impl PlatformAtlas for DirectXAtlas { .ok_or_else(|| anyhow::anyhow!("failed to allocate"))?; let texture = lock.texture(tile.texture_id); texture.upload(&lock.device_context, tile.bounds, &bytes); - lock.tiles_by_key.insert(key.clone(), tile.clone()); + lock.tiles_by_key.insert(key.clone(), tile); Ok(Some(tile)) } } diff --git a/crates/gpui_windows/src/window.rs b/crates/gpui_windows/src/window.rs index f655c1989e2c69743032703532f91b3b517084b6..405d415d713aea85a3784a7e11f818c58b9d228c 100644 --- a/crates/gpui_windows/src/window.rs +++ b/crates/gpui_windows/src/window.rs @@ -174,7 +174,7 @@ impl WindowsWindowState { } pub(crate) fn is_maximized(&self) -> bool { - !self.is_fullscreen() && unsafe { IsZoomed(self.hwnd) }.as_bool() + !self.is_fullscreen() } fn bounds(&self) -> Bounds { diff --git a/crates/multi_buffer/src/anchor.rs b/crates/multi_buffer/src/anchor.rs index b6a4dae1a27eb75664505bd224811e12f1240538..6a8e3b86af0075a98ab981c519e19f81435a5696 100644 --- a/crates/multi_buffer/src/anchor.rs +++ b/crates/multi_buffer/src/anchor.rs @@ -103,15 +103,16 @@ impl ExcerptAnchor { } pub(crate) fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> Ordering { - let Some(self_path_key) = snapshot.path_keys_by_index.get(&self.path) else { + let Some(self_path_key) = snapshot.path_keys.get_index(self.path.0 as usize) else { panic!("anchor's path was never added to multibuffer") }; - let Some(other_path_key) = snapshot.path_keys_by_index.get(&other.path) else { + let Some(other_path_key) = snapshot.path_keys.get_index(other.path.0 as usize) else { panic!("anchor's path was never added to multibuffer") }; - if self_path_key.cmp(other_path_key) != Ordering::Equal { - return self_path_key.cmp(other_path_key); + match self_path_key.cmp(other_path_key) { + Ordering::Equal => (), + ordering => return ordering, } // in the case that you removed the buffer containing self, @@ -122,16 +123,19 @@ impl ExcerptAnchor { } // two anchors into the same buffer at the same path - // TODO(cole) buffer_for_path is slow let Some(buffer) = snapshot - .buffer_for_path(&self_path_key) - .filter(|buffer| buffer.remote_id() == self.text_anchor.buffer_id) + .buffers + .get(&self.text_anchor.buffer_id) + .filter(|buffer_state| buffer_state.path_key == *self_path_key) else { // buffer no longer exists at the original path (which may have been reused for a different buffer), // so no way to compare the anchors return Ordering::Equal; }; - let text_cmp = self.text_anchor().cmp(&other.text_anchor(), buffer); + // two anchors into the same buffer at the same path that still exists at that path in the multibuffer + let text_cmp = self + .text_anchor() + .cmp(&other.text_anchor(), &buffer.buffer_snapshot); if text_cmp != Ordering::Equal { return text_cmp; } diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index 16d748dc3d9d6fc12d690f80bf317694986fffcf..801c7728a80a47a75254f1712b42a7e10a034ea8 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -15,7 +15,7 @@ use buffer_diff::{ DiffHunkStatus, DiffHunkStatusKind, }; use clock::ReplicaId; -use collections::{BTreeMap, Bound, HashMap, HashSet}; +use collections::{BTreeMap, Bound, HashMap, HashSet, IndexSet}; use gpui::{App, Context, Entity, EventEmitter}; use itertools::Itertools; use language::{ @@ -676,7 +676,7 @@ impl DiffState { #[derive(Clone)] struct BufferStateSnapshot { - path_key: PathKey, + pub(crate) path_key: PathKey, path_key_index: PathKeyIndex, buffer_snapshot: BufferSnapshot, } @@ -695,8 +695,7 @@ impl fmt::Debug for BufferStateSnapshot { pub struct MultiBufferSnapshot { excerpts: SumTree, buffers: TreeMap, - path_keys_by_index: TreeMap, - indices_by_path_key: TreeMap, + path_keys: Arc>, diffs: SumTree, diff_transforms: SumTree, non_text_state_update_count: usize, @@ -1802,8 +1801,7 @@ impl MultiBuffer { show_deleted_hunks: _, use_extended_diff_range: _, show_headers: _, - path_keys_by_index: _, - indices_by_path_key: _, + path_keys: _, buffers, } = self.snapshot.get_mut(); let start = ExcerptDimension(MultiBufferOffset::ZERO); @@ -2497,8 +2495,7 @@ impl MultiBuffer { excerpts, diffs: buffer_diff, buffers: buffer_snapshots, - path_keys_by_index: _, - indices_by_path_key: _, + path_keys: _, diff_transforms: _, non_text_state_update_count, edit_count, @@ -3582,7 +3579,7 @@ impl MultiBufferSnapshot { let Some(excerpt) = cursor.item() else { break; }; - if &excerpt.path_key != path { + if excerpt.path_key != *path { break; } let buffer_snapshot = excerpt.buffer_snapshot(self); @@ -6356,13 +6353,6 @@ impl MultiBufferSnapshot { )) } - pub fn buffer_for_path(&self, path: &PathKey) -> Option<&BufferSnapshot> { - let (_, _, excerpt) = self - .excerpts - .find::((), path, Bias::Left); - Some(excerpt?.buffer_snapshot(self)) - } - pub fn path_for_buffer(&self, buffer_id: BufferId) -> Option<&PathKey> { Some(&self.buffers.get(&buffer_id)?.path_key) } @@ -6378,9 +6368,7 @@ impl MultiBufferSnapshot { } fn first_excerpt_for_path(&self, path_key: &PathKey) -> Option<&Excerpt> { - let (_, _, first_excerpt) = - self.excerpts - .find::((), path_key, Bias::Left); + let (_, _, first_excerpt) = self.excerpts.find::((), path_key, Bias::Left); first_excerpt } @@ -6389,7 +6377,7 @@ impl MultiBufferSnapshot { } fn try_path_for_anchor(&self, anchor: ExcerptAnchor) -> Option<&PathKey> { - self.path_keys_by_index.get(&anchor.path) + self.path_keys.get_index(anchor.path.0 as usize) } pub fn path_for_anchor(&self, anchor: ExcerptAnchor) -> &PathKey { @@ -6831,7 +6819,7 @@ impl MultiBufferSnapshot { excerpt.path_key ); assert_eq!( - self.path_keys_by_index.get(&excerpt.path_key_index), + self.path_keys.get_index(excerpt.path_key_index.0 as usize), Some(&excerpt.path_key), "excerpt path key index does not match path key: {:#?}", excerpt.path_key, @@ -7470,6 +7458,23 @@ impl sum_tree::SeekTarget<'_, ExcerptSummary, ExcerptSummary> for AnchorSeekTarg } } +impl sum_tree::ContextLessSummary for PathKey { + fn zero() -> Self { + PathKey::min() + } + + fn add_summary(&mut self, summary: &Self) { + debug_assert!( + summary >= self, + "Path keys must be in ascending order: {:?} > {:?}", + summary, + self + ); + + *self = summary.clone(); + } +} + impl sum_tree::SeekTarget<'_, ExcerptSummary, ExcerptSummary> for PathKey { fn cmp( &self, diff --git a/crates/multi_buffer/src/path_key.rs b/crates/multi_buffer/src/path_key.rs index 5c2123d0f9c1b09c16fd99531973df81c45140f7..8424e163bbcd9c1fe4f0e89a5839a3277d13e1b1 100644 --- a/crates/multi_buffer/src/path_key.rs +++ b/crates/multi_buffer/src/path_key.rs @@ -253,8 +253,8 @@ impl MultiBuffer { for (path_index, excerpt_anchors) in &buffers { let path = snapshot - .path_keys_by_index - .get(&path_index) + .path_keys + .get_index(path_index.0 as usize) .expect("anchor from wrong multibuffer"); let mut excerpt_anchors = excerpt_anchors.peekable(); @@ -353,18 +353,15 @@ impl MultiBuffer { pub(crate) fn get_or_create_path_key_index(&mut self, path_key: &PathKey) -> PathKeyIndex { let mut snapshot = self.snapshot.borrow_mut(); - if let Some(&existing) = snapshot.indices_by_path_key.get(path_key) { - return existing; + if let Some(existing) = snapshot.path_keys.get_index_of(path_key) { + return PathKeyIndex(existing as u64); } - let index = snapshot - .path_keys_by_index - .last() - .map(|(index, _)| PathKeyIndex(index.0 + 1)) - .unwrap_or(PathKeyIndex(0)); - snapshot.path_keys_by_index.insert(index, path_key.clone()); - snapshot.indices_by_path_key.insert(path_key.clone(), index); - index + PathKeyIndex( + Arc::make_mut(&mut snapshot.path_keys) + .insert_full(path_key.clone()) + .0 as u64, + ) } pub fn update_path_excerpts( diff --git a/crates/title_bar/Cargo.toml b/crates/title_bar/Cargo.toml index eed94c839c0d0489944bf64725537234052c8e5f..ed7b64c3c18f3c77d856da166c11d3a224b49f24 100644 --- a/crates/title_bar/Cargo.toml +++ b/crates/title_bar/Cargo.toml @@ -59,6 +59,7 @@ ui.workspace = true util.workspace = true workspace.workspace = true zed_actions.workspace = true +arrayvec = "0.7.6" [target.'cfg(windows)'.dependencies] windows.workspace = true diff --git a/crates/title_bar/src/title_bar.rs b/crates/title_bar/src/title_bar.rs index a3804b450ba6d198b33d3ab8560d8415799ff8e9..95d022e5fb95a8cb5bd87df5ca254bf6b38b8b0c 100644 --- a/crates/title_bar/src/title_bar.rs +++ b/crates/title_bar/src/title_bar.rs @@ -7,6 +7,7 @@ mod update_version; use crate::application_menu::{ApplicationMenu, show_menus}; use crate::plan_chip::PlanChip; +use arrayvec::ArrayVec; use git_ui::worktree_picker::WorktreePicker; pub use platform_title_bar::{ self, DraggedWindowTab, MergeAllWindows, MoveTabToNewWindow, PlatformTitleBar, @@ -177,7 +178,7 @@ impl Render for TitleBar { let show_menus = show_menus(cx); - let mut children = Vec::new(); + let mut children = >::new(); let mut project_name = None; let mut repository = None;