Detailed changes
@@ -5344,6 +5344,7 @@ dependencies = [
"text",
"theme",
"time",
+ "tracing",
"tree-sitter-bash",
"tree-sitter-c",
"tree-sitter-html",
@@ -5363,6 +5364,7 @@ dependencies = [
"workspace",
"zed_actions",
"zlog",
+ "ztracing",
]
[[package]]
@@ -6824,6 +6826,20 @@ dependencies = [
"seq-macro",
]
+[[package]]
+name = "generator"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2"
+dependencies = [
+ "cc",
+ "cfg-if",
+ "libc",
+ "log",
+ "rustversion",
+ "windows 0.61.3",
+]
+
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -7042,6 +7058,7 @@ dependencies = [
"theme",
"time",
"time_format",
+ "tracing",
"ui",
"unindent",
"util",
@@ -7051,6 +7068,7 @@ dependencies = [
"zed_actions",
"zeroize",
"zlog",
+ "ztracing",
]
[[package]]
@@ -9373,6 +9391,19 @@ dependencies = [
"value-bag",
]
+[[package]]
+name = "loom"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
+dependencies = [
+ "cfg-if",
+ "generator",
+ "scoped-tls",
+ "tracing",
+ "tracing-subscriber",
+]
+
[[package]]
name = "loop9"
version = "0.1.5"
@@ -10043,9 +10074,11 @@ dependencies = [
"sum_tree",
"text",
"theme",
+ "tracing",
"tree-sitter",
"util",
"zlog",
+ "ztracing",
]
[[package]]
@@ -12400,6 +12433,7 @@ dependencies = [
"terminal",
"text",
"toml 0.8.23",
+ "tracing",
"unindent",
"url",
"util",
@@ -12409,6 +12443,7 @@ dependencies = [
"worktree",
"zeroize",
"zlog",
+ "ztracing",
]
[[package]]
@@ -13677,9 +13712,11 @@ dependencies = [
"rand 0.9.2",
"rayon",
"sum_tree",
+ "tracing",
"unicode-segmentation",
"util",
"zlog",
+ "ztracing",
]
[[package]]
@@ -15615,7 +15652,9 @@ dependencies = [
"log",
"rand 0.9.2",
"rayon",
+ "tracing",
"zlog",
+ "ztracing",
]
[[package]]
@@ -17100,9 +17139,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
-version = "0.1.41"
+version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
dependencies = [
"log",
"pin-project-lite",
@@ -17112,9 +17151,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.30"
+version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
+checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
@@ -17123,9 +17162,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.34"
+version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
+checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
dependencies = [
"once_cell",
"valuable",
@@ -17154,9 +17193,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.3.20"
+version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
+checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
dependencies = [
"matchers",
"nu-ansi-term",
@@ -17173,6 +17212,38 @@ dependencies = [
"tracing-serde",
]
+[[package]]
+name = "tracing-tracy"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba"
+dependencies = [
+ "tracing-core",
+ "tracing-subscriber",
+ "tracy-client",
+]
+
+[[package]]
+name = "tracy-client"
+version = "0.18.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91d722a05fe49b31fef971c4732a7d4aa6a18283d9ba46abddab35f484872947"
+dependencies = [
+ "loom",
+ "once_cell",
+ "tracy-client-sys",
+]
+
+[[package]]
+name = "tracy-client-sys"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fb391ac70462b3097a755618fbf9c8f95ecc1eb379a414f7b46f202ed10db1f"
+dependencies = [
+ "cc",
+ "windows-targets 0.52.6",
+]
+
[[package]]
name = "trait-variant"
version = "0.1.2"
@@ -20515,6 +20586,7 @@ dependencies = [
"time",
"title_bar",
"toolchain_selector",
+ "tracing",
"tree-sitter-md",
"tree-sitter-rust",
"ui",
@@ -20537,6 +20609,7 @@ dependencies = [
"zed_env_vars",
"zlog",
"zlog_settings",
+ "ztracing",
]
[[package]]
@@ -20931,6 +21004,20 @@ dependencies = [
"pkg-config",
]
+[[package]]
+name = "ztracing"
+version = "0.1.0"
+dependencies = [
+ "tracing",
+ "tracing-subscriber",
+ "tracing-tracy",
+ "ztracing_macro",
+]
+
+[[package]]
+name = "ztracing_macro"
+version = "0.1.0"
+
[[package]]
name = "zune-core"
version = "0.4.12"
@@ -204,6 +204,8 @@ members = [
"crates/edit_prediction_cli",
"crates/zlog",
"crates/zlog_settings",
+ "crates/ztracing",
+ "crates/ztracing_macro",
#
# Extensions
@@ -434,6 +436,8 @@ zed_env_vars = { path = "crates/zed_env_vars" }
edit_prediction = { path = "crates/edit_prediction" }
zlog = { path = "crates/zlog" }
zlog_settings = { path = "crates/zlog_settings" }
+ztracing = { path = "crates/ztracing" }
+ztracing_macro = { path = "crates/ztracing_macro" }
#
# External crates
@@ -694,6 +698,8 @@ tree-sitter-ruby = "0.23"
tree-sitter-rust = "0.24"
tree-sitter-typescript = { git = "https://github.com/zed-industries/tree-sitter-typescript", rev = "e2c53597d6a5d9cf7bbe8dccde576fe1e46c5899" } # https://github.com/tree-sitter/tree-sitter-typescript/pull/347
tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "baff0b51c64ef6a1fb1f8390f3ad6015b83ec13a" }
+tracing = "0.1.40"
+tracing-tracy = "0.11.4"
unicase = "2.6"
unicode-script = "0.5.7"
unicode-segmentation = "1.10"
@@ -65,7 +65,7 @@ tokio = { workspace = true, features = ["full"] }
toml.workspace = true
tower = "0.4"
tower-http = { workspace = true, features = ["trace"] }
-tracing = "0.1.40"
+tracing.workspace = true
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json", "registry", "tracing-log"] } # workaround for https://github.com/tokio-rs/tracing/issues/2927
util.workspace = true
uuid.workspace = true
@@ -84,6 +84,8 @@ tree-sitter-html = { workspace = true, optional = true }
tree-sitter-rust = { workspace = true, optional = true }
tree-sitter-typescript = { workspace = true, optional = true }
tree-sitter-python = { workspace = true, optional = true }
+ztracing.workspace = true
+tracing.workspace = true
unicode-segmentation.workspace = true
unicode-script.workspace = true
unindent = { workspace = true, optional = true }
@@ -94,6 +96,7 @@ uuid.workspace = true
vim_mode_setting.workspace = true
workspace.workspace = true
zed_actions.workspace = true
+zlog.workspace = true
[dev-dependencies]
criterion.workspace = true
@@ -164,6 +164,7 @@ impl<T> BlockPlacement<T> {
}
impl BlockPlacement<Anchor> {
+ #[ztracing::instrument(skip_all)]
fn cmp(&self, other: &Self, buffer: &MultiBufferSnapshot) -> Ordering {
self.start()
.cmp(other.start(), buffer)
@@ -171,6 +172,7 @@ impl BlockPlacement<Anchor> {
.then_with(|| self.tie_break().cmp(&other.tie_break()))
}
+ #[ztracing::instrument(skip_all)]
fn to_wrap_row(&self, wrap_snapshot: &WrapSnapshot) -> Option<BlockPlacement<WrapRow>> {
let buffer_snapshot = wrap_snapshot.buffer_snapshot();
match self {
@@ -474,6 +476,7 @@ pub struct BlockRows<'a> {
}
impl BlockMap {
+ #[ztracing::instrument(skip_all)]
pub fn new(
wrap_snapshot: WrapSnapshot,
buffer_header_height: u32,
@@ -503,6 +506,7 @@ impl BlockMap {
map
}
+ #[ztracing::instrument(skip_all)]
pub fn read(&self, wrap_snapshot: WrapSnapshot, edits: WrapPatch) -> BlockMapReader<'_> {
self.sync(&wrap_snapshot, edits);
*self.wrap_snapshot.borrow_mut() = wrap_snapshot.clone();
@@ -518,13 +522,17 @@ impl BlockMap {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn write(&mut self, wrap_snapshot: WrapSnapshot, edits: WrapPatch) -> BlockMapWriter<'_> {
self.sync(&wrap_snapshot, edits);
*self.wrap_snapshot.borrow_mut() = wrap_snapshot;
BlockMapWriter(self)
}
+ #[ztracing::instrument(skip_all, fields(edits))]
fn sync(&self, wrap_snapshot: &WrapSnapshot, mut edits: WrapPatch) {
+ let _timer = zlog::time!("BlockMap::sync").warn_if_gt(std::time::Duration::from_millis(50));
+
let buffer = wrap_snapshot.buffer_snapshot();
// Handle changing the last excerpt if it is empty.
@@ -784,6 +792,7 @@ impl BlockMap {
*transforms = new_transforms;
}
+ #[ztracing::instrument(skip_all)]
pub fn replace_blocks(&mut self, mut renderers: HashMap<CustomBlockId, RenderBlock>) {
for block in &mut self.custom_blocks {
if let Some(render) = renderers.remove(&block.id) {
@@ -793,6 +802,7 @@ impl BlockMap {
}
/// Guarantees that `wrap_row_for` is called with points in increasing order.
+ #[ztracing::instrument(skip_all)]
fn header_and_footer_blocks<'a, R, T>(
&'a self,
buffer: &'a multi_buffer::MultiBufferSnapshot,
@@ -880,6 +890,7 @@ impl BlockMap {
})
}
+ #[ztracing::instrument(skip_all)]
fn sort_blocks(blocks: &mut Vec<(BlockPlacement<WrapRow>, Block)>) {
blocks.sort_unstable_by(|(placement_a, block_a), (placement_b, block_b)| {
placement_a
@@ -1016,6 +1027,7 @@ impl DerefMut for BlockMapReader<'_> {
}
impl BlockMapReader<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn row_for_block(&self, block_id: CustomBlockId) -> Option<BlockRow> {
let block = self.blocks.iter().find(|block| block.id == block_id)?;
let buffer_row = block
@@ -1054,6 +1066,7 @@ impl BlockMapReader<'_> {
}
impl BlockMapWriter<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn insert(
&mut self,
blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
@@ -1120,6 +1133,7 @@ impl BlockMapWriter<'_> {
ids
}
+ #[ztracing::instrument(skip_all)]
pub fn resize(&mut self, mut heights: HashMap<CustomBlockId, u32>) {
let wrap_snapshot = &*self.0.wrap_snapshot.borrow();
let buffer = wrap_snapshot.buffer_snapshot();
@@ -1172,6 +1186,7 @@ impl BlockMapWriter<'_> {
self.0.sync(wrap_snapshot, edits);
}
+ #[ztracing::instrument(skip_all)]
pub fn remove(&mut self, block_ids: HashSet<CustomBlockId>) {
let wrap_snapshot = &*self.0.wrap_snapshot.borrow();
let buffer = wrap_snapshot.buffer_snapshot();
@@ -1217,6 +1232,7 @@ impl BlockMapWriter<'_> {
self.0.sync(wrap_snapshot, edits);
}
+ #[ztracing::instrument(skip_all)]
pub fn remove_intersecting_replace_blocks(
&mut self,
ranges: impl IntoIterator<Item = Range<MultiBufferOffset>>,
@@ -1239,6 +1255,7 @@ impl BlockMapWriter<'_> {
self.0.buffers_with_disabled_headers.insert(buffer_id);
}
+ #[ztracing::instrument(skip_all)]
pub fn fold_buffers(
&mut self,
buffer_ids: impl IntoIterator<Item = BufferId>,
@@ -1248,6 +1265,7 @@ impl BlockMapWriter<'_> {
self.fold_or_unfold_buffers(true, buffer_ids, multi_buffer, cx);
}
+ #[ztracing::instrument(skip_all)]
pub fn unfold_buffers(
&mut self,
buffer_ids: impl IntoIterator<Item = BufferId>,
@@ -1257,6 +1275,7 @@ impl BlockMapWriter<'_> {
self.fold_or_unfold_buffers(false, buffer_ids, multi_buffer, cx);
}
+ #[ztracing::instrument(skip_all)]
fn fold_or_unfold_buffers(
&mut self,
fold: bool,
@@ -1292,6 +1311,7 @@ impl BlockMapWriter<'_> {
self.0.sync(&wrap_snapshot, edits);
}
+ #[ztracing::instrument(skip_all)]
fn blocks_intersecting_buffer_range(
&self,
range: Range<MultiBufferOffset>,
@@ -1326,6 +1346,7 @@ impl BlockMapWriter<'_> {
impl BlockSnapshot {
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub fn text(&self) -> String {
self.chunks(
BlockRow(0)..self.transforms.summary().output_rows,
@@ -1337,6 +1358,7 @@ impl BlockSnapshot {
.collect()
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn chunks<'a>(
&'a self,
rows: Range<BlockRow>,
@@ -1378,6 +1400,7 @@ impl BlockSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub(super) fn row_infos(&self, start_row: BlockRow) -> BlockRows<'_> {
let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
cursor.seek(&start_row, Bias::Right);
@@ -1399,6 +1422,7 @@ impl BlockSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn blocks_in_range(
&self,
rows: Range<BlockRow>,
@@ -1432,6 +1456,7 @@ impl BlockSnapshot {
})
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn sticky_header_excerpt(&self, position: f64) -> Option<StickyHeaderExcerpt<'_>> {
let top_row = position as u32;
let mut cursor = self.transforms.cursor::<BlockRow>(());
@@ -1455,6 +1480,7 @@ impl BlockSnapshot {
None
}
+ #[ztracing::instrument(skip_all)]
pub fn block_for_id(&self, block_id: BlockId) -> Option<Block> {
let buffer = self.wrap_snapshot.buffer_snapshot();
let wrap_point = match block_id {
@@ -1491,6 +1517,7 @@ impl BlockSnapshot {
None
}
+ #[ztracing::instrument(skip_all)]
pub fn max_point(&self) -> BlockPoint {
let row = self
.transforms
@@ -1500,10 +1527,12 @@ impl BlockSnapshot {
BlockPoint::new(row, self.line_len(row))
}
+ #[ztracing::instrument(skip_all)]
pub fn longest_row(&self) -> BlockRow {
self.transforms.summary().longest_row
}
+ #[ztracing::instrument(skip_all)]
pub fn longest_row_in_range(&self, range: Range<BlockRow>) -> BlockRow {
let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
cursor.seek(&range.start, Bias::Right);
@@ -1555,6 +1584,7 @@ impl BlockSnapshot {
longest_row
}
+ #[ztracing::instrument(skip_all)]
pub(super) fn line_len(&self, row: BlockRow) -> u32 {
let (start, _, item) =
self.transforms
@@ -1574,11 +1604,13 @@ impl BlockSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub(super) fn is_block_line(&self, row: BlockRow) -> bool {
let (_, _, item) = self.transforms.find::<BlockRow, _>((), &row, Bias::Right);
item.is_some_and(|t| t.block.is_some())
}
+ #[ztracing::instrument(skip_all)]
pub(super) fn is_folded_buffer_header(&self, row: BlockRow) -> bool {
let (_, _, item) = self.transforms.find::<BlockRow, _>((), &row, Bias::Right);
let Some(transform) = item else {
@@ -1587,6 +1619,7 @@ impl BlockSnapshot {
matches!(transform.block, Some(Block::FoldedBuffer { .. }))
}
+ #[ztracing::instrument(skip_all)]
pub(super) fn is_line_replaced(&self, row: MultiBufferRow) -> bool {
let wrap_point = self
.wrap_snapshot
@@ -1602,6 +1635,7 @@ impl BlockSnapshot {
})
}
+ #[ztracing::instrument(skip_all)]
pub fn clip_point(&self, point: BlockPoint, bias: Bias) -> BlockPoint {
let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
cursor.seek(&BlockRow(point.row), Bias::Right);
@@ -1663,6 +1697,7 @@ impl BlockSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn to_block_point(&self, wrap_point: WrapPoint) -> BlockPoint {
let (start, _, item) = self.transforms.find::<Dimensions<WrapRow, BlockRow>, _>(
(),
@@ -1684,6 +1719,7 @@ impl BlockSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn to_wrap_point(&self, block_point: BlockPoint, bias: Bias) -> WrapPoint {
let (start, end, item) = self.transforms.find::<Dimensions<BlockRow, WrapRow>, _>(
(),
@@ -1719,6 +1755,7 @@ impl BlockSnapshot {
impl BlockChunks<'_> {
/// Go to the next transform
+ #[ztracing::instrument(skip_all)]
fn advance(&mut self) {
self.input_chunk = Chunk::default();
self.transforms.next();
@@ -1759,6 +1796,7 @@ pub struct StickyHeaderExcerpt<'a> {
impl<'a> Iterator for BlockChunks<'a> {
type Item = Chunk<'a>;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
if self.output_row >= self.max_output_row {
return None;
@@ -1858,6 +1896,7 @@ impl<'a> Iterator for BlockChunks<'a> {
impl Iterator for BlockRows<'_> {
type Item = RowInfo;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
if self.started {
self.output_row.0 += 1;
@@ -1960,14 +1999,17 @@ impl DerefMut for BlockContext<'_, '_> {
}
impl CustomBlock {
+ #[ztracing::instrument(skip_all)]
pub fn render(&self, cx: &mut BlockContext) -> AnyElement {
self.render.lock()(cx)
}
+ #[ztracing::instrument(skip_all)]
pub fn start(&self) -> Anchor {
*self.placement.start()
}
+ #[ztracing::instrument(skip_all)]
pub fn end(&self) -> Anchor {
*self.placement.end()
}
@@ -19,6 +19,7 @@ pub struct CreaseMap {
}
impl CreaseMap {
+ #[ztracing::instrument(skip_all)]
pub fn new(snapshot: &MultiBufferSnapshot) -> Self {
CreaseMap {
snapshot: CreaseSnapshot::new(snapshot),
@@ -40,11 +41,13 @@ impl CreaseSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn creases(&self) -> impl Iterator<Item = (CreaseId, &Crease<Anchor>)> {
self.creases.iter().map(|item| (item.id, &item.crease))
}
/// Returns the first Crease starting on the specified buffer row.
+ #[ztracing::instrument(skip_all)]
pub fn query_row<'a>(
&'a self,
row: MultiBufferRow,
@@ -69,6 +72,7 @@ impl CreaseSnapshot {
None
}
+ #[ztracing::instrument(skip_all)]
pub fn creases_in_range<'a>(
&'a self,
range: Range<MultiBufferRow>,
@@ -95,6 +99,7 @@ impl CreaseSnapshot {
})
}
+ #[ztracing::instrument(skip_all)]
pub fn crease_items_with_offsets(
&self,
snapshot: &MultiBufferSnapshot,
@@ -156,6 +161,7 @@ pub struct CreaseMetadata {
}
impl<T> Crease<T> {
+ #[ztracing::instrument(skip_all)]
pub fn simple(range: Range<T>, placeholder: FoldPlaceholder) -> Self {
Crease::Inline {
range,
@@ -166,6 +172,7 @@ impl<T> Crease<T> {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn block(range: Range<T>, height: u32, style: BlockStyle, render: RenderBlock) -> Self {
Self::Block {
range,
@@ -177,6 +184,7 @@ impl<T> Crease<T> {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn inline<RenderToggle, ToggleElement, RenderTrailer, TrailerElement>(
range: Range<T>,
placeholder: FoldPlaceholder,
@@ -216,6 +224,7 @@ impl<T> Crease<T> {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn with_metadata(self, metadata: CreaseMetadata) -> Self {
match self {
Crease::Inline {
@@ -235,6 +244,7 @@ impl<T> Crease<T> {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn range(&self) -> &Range<T> {
match self {
Crease::Inline { range, .. } => range,
@@ -242,6 +252,7 @@ impl<T> Crease<T> {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn metadata(&self) -> Option<&CreaseMetadata> {
match self {
Self::Inline { metadata, .. } => metadata.as_ref(),
@@ -287,6 +298,7 @@ impl CreaseMap {
self.snapshot.clone()
}
+ #[ztracing::instrument(skip_all)]
pub fn insert(
&mut self,
creases: impl IntoIterator<Item = Crease<Anchor>>,
@@ -312,6 +324,7 @@ impl CreaseMap {
new_ids
}
+ #[ztracing::instrument(skip_all)]
pub fn remove(
&mut self,
ids: impl IntoIterator<Item = CreaseId>,
@@ -379,6 +392,7 @@ impl sum_tree::Summary for ItemSummary {
impl sum_tree::Item for CreaseItem {
type Summary = ItemSummary;
+ #[ztracing::instrument(skip_all)]
fn summary(&self, _cx: &MultiBufferSnapshot) -> Self::Summary {
ItemSummary {
range: self.crease.range().clone(),
@@ -388,12 +402,14 @@ impl sum_tree::Item for CreaseItem {
/// Implements `SeekTarget` for `Range<Anchor>` to enable seeking within a `SumTree` of `CreaseItem`s.
impl SeekTarget<'_, ItemSummary, ItemSummary> for Range<Anchor> {
+ #[ztracing::instrument(skip_all)]
fn cmp(&self, cursor_location: &ItemSummary, snapshot: &MultiBufferSnapshot) -> Ordering {
AnchorRangeExt::cmp(self, &cursor_location.range, snapshot)
}
}
impl SeekTarget<'_, ItemSummary, ItemSummary> for Anchor {
+ #[ztracing::instrument(skip_all)]
fn cmp(&self, other: &ItemSummary, snapshot: &MultiBufferSnapshot) -> Ordering {
self.cmp(&other.range.start, snapshot)
}
@@ -461,6 +477,7 @@ mod test {
}
#[gpui::test]
+ #[ztracing::instrument(skip_all)]
fn test_creases_in_range(cx: &mut App) {
let text = "line1\nline2\nline3\nline4\nline5\nline6\nline7";
let buffer = MultiBuffer::build_simple(text, cx);
@@ -30,6 +30,7 @@ struct HighlightEndpoint {
}
impl<'a> CustomHighlightsChunks<'a> {
+ #[ztracing::instrument(skip_all)]
pub fn new(
range: Range<MultiBufferOffset>,
language_aware: bool,
@@ -51,6 +52,7 @@ impl<'a> CustomHighlightsChunks<'a> {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn seek(&mut self, new_range: Range<MultiBufferOffset>) {
self.highlight_endpoints =
create_highlight_endpoints(&new_range, self.text_highlights, self.multibuffer_snapshot);
@@ -108,6 +110,7 @@ fn create_highlight_endpoints(
impl<'a> Iterator for CustomHighlightsChunks<'a> {
type Item = Chunk<'a>;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
let mut next_highlight_endpoint = MultiBufferOffset(usize::MAX);
while let Some(endpoint) = self.highlight_endpoints.peek().copied() {
@@ -99,6 +99,7 @@ impl FoldPoint {
&mut self.0.column
}
+ #[ztracing::instrument(skip_all)]
pub fn to_inlay_point(self, snapshot: &FoldSnapshot) -> InlayPoint {
let (start, _, _) = snapshot
.transforms
@@ -107,6 +108,7 @@ impl FoldPoint {
InlayPoint(start.1.0 + overshoot)
}
+ #[ztracing::instrument(skip_all)]
pub fn to_offset(self, snapshot: &FoldSnapshot) -> FoldOffset {
let (start, _, item) = snapshot
.transforms
@@ -138,6 +140,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldPoint {
pub(crate) struct FoldMapWriter<'a>(&'a mut FoldMap);
impl FoldMapWriter<'_> {
+ #[ztracing::instrument(skip_all)]
pub(crate) fn fold<T: ToOffset>(
&mut self,
ranges: impl IntoIterator<Item = (Range<T>, FoldPlaceholder)>,
@@ -202,6 +205,7 @@ impl FoldMapWriter<'_> {
}
/// Removes any folds with the given ranges.
+ #[ztracing::instrument(skip_all)]
pub(crate) fn remove_folds<T: ToOffset>(
&mut self,
ranges: impl IntoIterator<Item = Range<T>>,
@@ -215,6 +219,7 @@ impl FoldMapWriter<'_> {
}
/// Removes any folds whose ranges intersect the given ranges.
+ #[ztracing::instrument(skip_all)]
pub(crate) fn unfold_intersecting<T: ToOffset>(
&mut self,
ranges: impl IntoIterator<Item = Range<T>>,
@@ -225,6 +230,7 @@ impl FoldMapWriter<'_> {
/// Removes any folds that intersect the given ranges and for which the given predicate
/// returns true.
+ #[ztracing::instrument(skip_all)]
fn remove_folds_with<T: ToOffset>(
&mut self,
ranges: impl IntoIterator<Item = Range<T>>,
@@ -277,6 +283,7 @@ impl FoldMapWriter<'_> {
(self.0.snapshot.clone(), edits)
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn update_fold_widths(
&mut self,
new_widths: impl IntoIterator<Item = (ChunkRendererId, Pixels)>,
@@ -326,6 +333,7 @@ pub struct FoldMap {
}
impl FoldMap {
+ #[ztracing::instrument(skip_all)]
pub fn new(inlay_snapshot: InlaySnapshot) -> (Self, FoldSnapshot) {
let this = Self {
snapshot: FoldSnapshot {
@@ -350,6 +358,7 @@ impl FoldMap {
(this, snapshot)
}
+ #[ztracing::instrument(skip_all)]
pub fn read(
&mut self,
inlay_snapshot: InlaySnapshot,
@@ -360,6 +369,7 @@ impl FoldMap {
(self.snapshot.clone(), edits)
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn write(
&mut self,
inlay_snapshot: InlaySnapshot,
@@ -369,6 +379,7 @@ impl FoldMap {
(FoldMapWriter(self), snapshot, edits)
}
+ #[ztracing::instrument(skip_all)]
fn check_invariants(&self) {
if cfg!(test) {
assert_eq!(
@@ -398,6 +409,7 @@ impl FoldMap {
}
}
+ #[ztracing::instrument(skip_all)]
fn sync(
&mut self,
inlay_snapshot: InlaySnapshot,
@@ -645,6 +657,7 @@ impl FoldSnapshot {
&self.inlay_snapshot.buffer
}
+ #[ztracing::instrument(skip_all)]
fn fold_width(&self, fold_id: &FoldId) -> Option<Pixels> {
self.fold_metadata_by_id.get(fold_id)?.width
}
@@ -665,6 +678,7 @@ impl FoldSnapshot {
self.folds.items(&self.inlay_snapshot.buffer).len()
}
+ #[ztracing::instrument(skip_all)]
pub fn text_summary_for_range(&self, range: Range<FoldPoint>) -> MBTextSummary {
let mut summary = MBTextSummary::default();
@@ -718,6 +732,7 @@ impl FoldSnapshot {
summary
}
+ #[ztracing::instrument(skip_all)]
pub fn to_fold_point(&self, point: InlayPoint, bias: Bias) -> FoldPoint {
let (start, end, item) = self
.transforms
@@ -734,6 +749,7 @@ impl FoldSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn fold_point_cursor(&self) -> FoldPointCursor<'_> {
let cursor = self
.transforms
@@ -741,10 +757,12 @@ impl FoldSnapshot {
FoldPointCursor { cursor }
}
+ #[ztracing::instrument(skip_all)]
pub fn len(&self) -> FoldOffset {
FoldOffset(self.transforms.summary().output.len)
}
+ #[ztracing::instrument(skip_all)]
pub fn line_len(&self, row: u32) -> u32 {
let line_start = FoldPoint::new(row, 0).to_offset(self).0;
let line_end = if row >= self.max_point().row() {
@@ -755,6 +773,7 @@ impl FoldSnapshot {
(line_end - line_start) as u32
}
+ #[ztracing::instrument(skip_all)]
pub fn row_infos(&self, start_row: u32) -> FoldRows<'_> {
if start_row > self.transforms.summary().output.lines.row {
panic!("invalid display row {}", start_row);
@@ -777,6 +796,7 @@ impl FoldSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn max_point(&self) -> FoldPoint {
FoldPoint(self.transforms.summary().output.lines)
}
@@ -786,6 +806,7 @@ impl FoldSnapshot {
self.transforms.summary().output.longest_row
}
+ #[ztracing::instrument(skip_all)]
pub fn folds_in_range<T>(&self, range: Range<T>) -> impl Iterator<Item = &Fold>
where
T: ToOffset,
@@ -800,6 +821,7 @@ impl FoldSnapshot {
})
}
+ #[ztracing::instrument(skip_all)]
pub fn intersects_fold<T>(&self, offset: T) -> bool
where
T: ToOffset,
@@ -812,6 +834,7 @@ impl FoldSnapshot {
item.is_some_and(|t| t.placeholder.is_some())
}
+ #[ztracing::instrument(skip_all)]
pub fn is_line_folded(&self, buffer_row: MultiBufferRow) -> bool {
let mut inlay_point = self
.inlay_snapshot
@@ -840,6 +863,7 @@ impl FoldSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn chunks<'a>(
&'a self,
range: Range<FoldOffset>,
@@ -884,6 +908,7 @@ impl FoldSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn chars_at(&self, start: FoldPoint) -> impl '_ + Iterator<Item = char> {
self.chunks(
start.to_offset(self)..self.len(),
@@ -893,6 +918,7 @@ impl FoldSnapshot {
.flat_map(|chunk| chunk.text.chars())
}
+ #[ztracing::instrument(skip_all)]
pub fn chunks_at(&self, start: FoldPoint) -> FoldChunks<'_> {
self.chunks(
start.to_offset(self)..self.len(),
@@ -902,6 +928,7 @@ impl FoldSnapshot {
}
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub fn clip_offset(&self, offset: FoldOffset, bias: Bias) -> FoldOffset {
if offset > self.len() {
self.len()
@@ -910,6 +937,7 @@ impl FoldSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn clip_point(&self, point: FoldPoint, bias: Bias) -> FoldPoint {
let (start, end, item) = self
.transforms
@@ -939,6 +967,7 @@ pub struct FoldPointCursor<'transforms> {
}
impl FoldPointCursor<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn map(&mut self, point: InlayPoint, bias: Bias) -> FoldPoint {
let cursor = &mut self.cursor;
if cursor.did_seek() {
@@ -1267,6 +1296,7 @@ pub struct FoldRows<'a> {
}
impl FoldRows<'_> {
+ #[ztracing::instrument(skip_all)]
pub(crate) fn seek(&mut self, row: u32) {
let fold_point = FoldPoint::new(row, 0);
self.cursor.seek(&fold_point, Bias::Left);
@@ -1280,6 +1310,7 @@ impl FoldRows<'_> {
impl Iterator for FoldRows<'_> {
type Item = RowInfo;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
let mut traversed_fold = false;
while self.fold_point > self.cursor.end().0 {
@@ -1391,6 +1422,7 @@ pub struct FoldChunks<'a> {
}
impl FoldChunks<'_> {
+ #[ztracing::instrument(skip_all)]
pub(crate) fn seek(&mut self, range: Range<FoldOffset>) {
self.transform_cursor.seek(&range.start, Bias::Right);
@@ -1425,6 +1457,7 @@ impl FoldChunks<'_> {
impl<'a> Iterator for FoldChunks<'a> {
type Item = Chunk<'a>;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
if self.output_offset >= self.max_output_offset {
return None;
@@ -1524,6 +1557,7 @@ impl<'a> Iterator for FoldChunks<'a> {
pub struct FoldOffset(pub MultiBufferOffset);
impl FoldOffset {
+ #[ztracing::instrument(skip_all)]
pub fn to_point(self, snapshot: &FoldSnapshot) -> FoldPoint {
let (start, _, item) = snapshot
.transforms
@@ -1539,6 +1573,7 @@ impl FoldOffset {
}
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub fn to_inlay_offset(self, snapshot: &FoldSnapshot) -> InlayOffset {
let (start, _, _) = snapshot
.transforms
@@ -52,6 +52,7 @@ enum Transform {
impl sum_tree::Item for Transform {
type Summary = TransformSummary;
+ #[ztracing::instrument(skip_all)]
fn summary(&self, _: ()) -> Self::Summary {
match self {
Transform::Isomorphic(summary) => TransformSummary {
@@ -228,6 +229,7 @@ pub struct InlayChunk<'a> {
}
impl InlayChunks<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn seek(&mut self, new_range: Range<InlayOffset>) {
self.transforms.seek(&new_range.start, Bias::Right);
@@ -248,6 +250,7 @@ impl InlayChunks<'_> {
impl<'a> Iterator for InlayChunks<'a> {
type Item = InlayChunk<'a>;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
if self.output_offset == self.max_output_offset {
return None;
@@ -441,6 +444,7 @@ impl<'a> Iterator for InlayChunks<'a> {
}
impl InlayBufferRows<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn seek(&mut self, row: u32) {
let inlay_point = InlayPoint::new(row, 0);
self.transforms.seek(&inlay_point, Bias::Left);
@@ -465,6 +469,7 @@ impl InlayBufferRows<'_> {
impl Iterator for InlayBufferRows<'_> {
type Item = RowInfo;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
let buffer_row = if self.inlay_row == 0 {
self.buffer_rows.next().unwrap()
@@ -494,6 +499,7 @@ impl InlayPoint {
}
impl InlayMap {
+ #[ztracing::instrument(skip_all)]
pub fn new(buffer: MultiBufferSnapshot) -> (Self, InlaySnapshot) {
let version = 0;
let snapshot = InlaySnapshot {
@@ -511,6 +517,7 @@ impl InlayMap {
)
}
+ #[ztracing::instrument(skip_all)]
pub fn sync(
&mut self,
buffer_snapshot: MultiBufferSnapshot,
@@ -643,6 +650,7 @@ impl InlayMap {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn splice(
&mut self,
to_remove: &[InlayId],
@@ -693,11 +701,13 @@ impl InlayMap {
(snapshot, edits)
}
+ #[ztracing::instrument(skip_all)]
pub fn current_inlays(&self) -> impl Iterator<Item = &Inlay> {
self.inlays.iter()
}
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub(crate) fn randomly_mutate(
&mut self,
next_inlay_id: &mut usize,
@@ -766,6 +776,7 @@ impl InlayMap {
}
impl InlaySnapshot {
+ #[ztracing::instrument(skip_all)]
pub fn to_point(&self, offset: InlayOffset) -> InlayPoint {
let (start, _, item) = self.transforms.find::<Dimensions<
InlayOffset,
@@ -789,14 +800,17 @@ impl InlaySnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn len(&self) -> InlayOffset {
InlayOffset(self.transforms.summary().output.len)
}
+ #[ztracing::instrument(skip_all)]
pub fn max_point(&self) -> InlayPoint {
InlayPoint(self.transforms.summary().output.lines)
}
+ #[ztracing::instrument(skip_all, fields(point))]
pub fn to_offset(&self, point: InlayPoint) -> InlayOffset {
let (start, _, item) = self
.transforms
@@ -817,6 +831,7 @@ impl InlaySnapshot {
None => self.len(),
}
}
+ #[ztracing::instrument(skip_all)]
pub fn to_buffer_point(&self, point: InlayPoint) -> Point {
let (start, _, item) =
self.transforms
@@ -830,6 +845,7 @@ impl InlaySnapshot {
None => self.buffer.max_point(),
}
}
+ #[ztracing::instrument(skip_all)]
pub fn to_buffer_offset(&self, offset: InlayOffset) -> MultiBufferOffset {
let (start, _, item) = self
.transforms
@@ -844,6 +860,7 @@ impl InlaySnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn to_inlay_offset(&self, offset: MultiBufferOffset) -> InlayOffset {
let mut cursor = self
.transforms
@@ -880,10 +897,12 @@ impl InlaySnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn to_inlay_point(&self, point: Point) -> InlayPoint {
self.inlay_point_cursor().map(point)
}
+ #[ztracing::instrument(skip_all)]
pub fn inlay_point_cursor(&self) -> InlayPointCursor<'_> {
let cursor = self.transforms.cursor::<Dimensions<Point, InlayPoint>>(());
InlayPointCursor {
@@ -892,6 +911,7 @@ impl InlaySnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn clip_point(&self, mut point: InlayPoint, mut bias: Bias) -> InlayPoint {
let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(());
cursor.seek(&point, Bias::Left);
@@ -983,10 +1003,12 @@ impl InlaySnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn text_summary(&self) -> MBTextSummary {
self.transforms.summary().output
}
+ #[ztracing::instrument(skip_all)]
pub fn text_summary_for_range(&self, range: Range<InlayOffset>) -> MBTextSummary {
let mut summary = MBTextSummary::default();
@@ -1044,6 +1066,7 @@ impl InlaySnapshot {
summary
}
+ #[ztracing::instrument(skip_all)]
pub fn row_infos(&self, row: u32) -> InlayBufferRows<'_> {
let mut cursor = self.transforms.cursor::<Dimensions<InlayPoint, Point>>(());
let inlay_point = InlayPoint::new(row, 0);
@@ -1071,6 +1094,7 @@ impl InlaySnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn line_len(&self, row: u32) -> u32 {
let line_start = self.to_offset(InlayPoint::new(row, 0)).0;
let line_end = if row >= self.max_point().row() {
@@ -1081,6 +1105,7 @@ impl InlaySnapshot {
(line_end - line_start) as u32
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn chunks<'a>(
&'a self,
range: Range<InlayOffset>,
@@ -1115,12 +1140,14 @@ impl InlaySnapshot {
}
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub fn text(&self) -> String {
self.chunks(Default::default()..self.len(), false, Highlights::default())
.map(|chunk| chunk.chunk.text)
.collect()
}
+ #[ztracing::instrument(skip_all)]
fn check_invariants(&self) {
#[cfg(any(debug_assertions, feature = "test-support"))]
{
@@ -1147,6 +1174,7 @@ pub struct InlayPointCursor<'transforms> {
}
impl InlayPointCursor<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn map(&mut self, point: Point) -> InlayPoint {
let cursor = &mut self.cursor;
if cursor.did_seek() {
@@ -30,6 +30,7 @@
// ref: https://gist.github.com/ConradIrwin/f759e1fc29267143c4c7895aa495dca5?h=1
// ref: https://unicode.org/Public/emoji/13.0/emoji-test.txt
// https://github.com/bits/UTF-8-Unicode-Test-Documents/blob/master/UTF-8_sequence_separated/utf8_sequence_0-0x10ffff_assigned_including-unprintable-asis.txt
+#[ztracing::instrument(skip_all)]
pub fn is_invisible(c: char) -> bool {
if c <= '\u{1f}' {
c != '\t' && c != '\n' && c != '\r'
@@ -20,6 +20,7 @@ const MAX_TABS: NonZeroU32 = NonZeroU32::new(SPACES.len() as u32).unwrap();
pub struct TabMap(TabSnapshot);
impl TabMap {
+ #[ztracing::instrument(skip_all)]
pub fn new(fold_snapshot: FoldSnapshot, tab_size: NonZeroU32) -> (Self, TabSnapshot) {
let snapshot = TabSnapshot {
fold_snapshot,
@@ -36,6 +37,7 @@ impl TabMap {
self.0.clone()
}
+ #[ztracing::instrument(skip_all)]
pub fn sync(
&mut self,
fold_snapshot: FoldSnapshot,
@@ -176,10 +178,12 @@ impl std::ops::Deref for TabSnapshot {
}
impl TabSnapshot {
+ #[ztracing::instrument(skip_all)]
pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot {
&self.fold_snapshot.inlay_snapshot.buffer
}
+ #[ztracing::instrument(skip_all)]
pub fn line_len(&self, row: u32) -> u32 {
let max_point = self.max_point();
if row < max_point.row() {
@@ -191,10 +195,12 @@ impl TabSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn text_summary(&self) -> TextSummary {
self.text_summary_for_range(TabPoint::zero()..self.max_point())
}
+ #[ztracing::instrument(skip_all, fields(rows))]
pub fn text_summary_for_range(&self, range: Range<TabPoint>) -> TextSummary {
let input_start = self.tab_point_to_fold_point(range.start, Bias::Left).0;
let input_end = self.tab_point_to_fold_point(range.end, Bias::Right).0;
@@ -234,6 +240,7 @@ impl TabSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn chunks<'a>(
&'a self,
range: Range<TabPoint>,
@@ -276,11 +283,13 @@ impl TabSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn rows(&self, row: u32) -> fold_map::FoldRows<'_> {
self.fold_snapshot.row_infos(row)
}
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub fn text(&self) -> String {
self.chunks(
TabPoint::zero()..self.max_point(),
@@ -291,10 +300,12 @@ impl TabSnapshot {
.collect()
}
+ #[ztracing::instrument(skip_all)]
pub fn max_point(&self) -> TabPoint {
self.fold_point_to_tab_point(self.fold_snapshot.max_point())
}
+ #[ztracing::instrument(skip_all)]
pub fn clip_point(&self, point: TabPoint, bias: Bias) -> TabPoint {
self.fold_point_to_tab_point(
self.fold_snapshot
@@ -302,6 +313,7 @@ impl TabSnapshot {
)
}
+ #[ztracing::instrument(skip_all)]
pub fn fold_point_to_tab_point(&self, input: FoldPoint) -> TabPoint {
let chunks = self.fold_snapshot.chunks_at(FoldPoint::new(input.row(), 0));
let tab_cursor = TabStopCursor::new(chunks);
@@ -309,10 +321,12 @@ impl TabSnapshot {
TabPoint::new(input.row(), expanded)
}
+ #[ztracing::instrument(skip_all)]
pub fn tab_point_cursor(&self) -> TabPointCursor<'_> {
TabPointCursor { this: self }
}
+ #[ztracing::instrument(skip_all)]
pub fn tab_point_to_fold_point(&self, output: TabPoint, bias: Bias) -> (FoldPoint, u32, u32) {
let chunks = self
.fold_snapshot
@@ -330,12 +344,14 @@ impl TabSnapshot {
)
}
+ #[ztracing::instrument(skip_all)]
pub fn point_to_tab_point(&self, point: Point, bias: Bias) -> TabPoint {
let inlay_point = self.fold_snapshot.inlay_snapshot.to_inlay_point(point);
let fold_point = self.fold_snapshot.to_fold_point(inlay_point, bias);
self.fold_point_to_tab_point(fold_point)
}
+ #[ztracing::instrument(skip_all)]
pub fn tab_point_to_point(&self, point: TabPoint, bias: Bias) -> Point {
let fold_point = self.tab_point_to_fold_point(point, bias).0;
let inlay_point = fold_point.to_inlay_point(&self.fold_snapshot);
@@ -344,6 +360,7 @@ impl TabSnapshot {
.to_buffer_point(inlay_point)
}
+ #[ztracing::instrument(skip_all)]
fn expand_tabs<'a, I>(&self, mut cursor: TabStopCursor<'a, I>, column: u32) -> u32
where
I: Iterator<Item = Chunk<'a>>,
@@ -377,6 +394,7 @@ impl TabSnapshot {
expanded_bytes + column.saturating_sub(collapsed_bytes)
}
+ #[ztracing::instrument(skip_all)]
fn collapse_tabs<'a, I>(
&self,
mut cursor: TabStopCursor<'a, I>,
@@ -442,6 +460,7 @@ pub struct TabPointCursor<'this> {
}
impl TabPointCursor<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn map(&mut self, point: FoldPoint) -> TabPoint {
self.this.fold_point_to_tab_point(point)
}
@@ -486,6 +505,7 @@ pub struct TextSummary {
}
impl<'a> From<&'a str> for TextSummary {
+ #[ztracing::instrument(skip_all)]
fn from(text: &'a str) -> Self {
let sum = text::TextSummary::from(text);
@@ -500,6 +520,7 @@ impl<'a> From<&'a str> for TextSummary {
}
impl<'a> std::ops::AddAssign<&'a Self> for TextSummary {
+ #[ztracing::instrument(skip_all)]
fn add_assign(&mut self, other: &'a Self) {
let joined_chars = self.last_line_chars + other.first_line_chars;
if joined_chars > self.longest_row_chars {
@@ -541,6 +562,7 @@ pub struct TabChunks<'a> {
}
impl TabChunks<'_> {
+ #[ztracing::instrument(skip_all)]
pub(crate) fn seek(&mut self, range: Range<TabPoint>) {
let (input_start, expanded_char_column, to_next_stop) = self
.snapshot
@@ -576,6 +598,7 @@ impl TabChunks<'_> {
impl<'a> Iterator for TabChunks<'a> {
type Item = Chunk<'a>;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
if self.chunk.text.is_empty() {
if let Some(chunk) = self.fold_chunks.next() {
@@ -1452,6 +1475,7 @@ impl<'a, I> TabStopCursor<'a, I>
where
I: Iterator<Item = Chunk<'a>>,
{
+ #[ztracing::instrument(skip_all)]
fn new(chunks: impl IntoIterator<Item = Chunk<'a>, IntoIter = I>) -> Self {
Self {
chunks: chunks.into_iter(),
@@ -1461,6 +1485,7 @@ where
}
}
+ #[ztracing::instrument(skip_all)]
fn bytes_until_next_char(&self) -> Option<usize> {
self.current_chunk.as_ref().and_then(|(chunk, idx)| {
let mut idx = *idx;
@@ -1482,6 +1507,7 @@ where
})
}
+ #[ztracing::instrument(skip_all)]
fn is_char_boundary(&self) -> bool {
self.current_chunk
.as_ref()
@@ -1489,6 +1515,7 @@ where
}
/// distance: length to move forward while searching for the next tab stop
+ #[ztracing::instrument(skip_all)]
fn seek(&mut self, distance: u32) -> Option<TabStop> {
if distance == 0 {
return None;
@@ -86,6 +86,7 @@ pub struct WrapRows<'a> {
}
impl WrapRows<'_> {
+ #[ztracing::instrument(skip_all)]
pub(crate) fn seek(&mut self, start_row: WrapRow) {
self.transforms
.seek(&WrapPoint::new(start_row, 0), Bias::Left);
@@ -101,6 +102,7 @@ impl WrapRows<'_> {
}
impl WrapMap {
+ #[ztracing::instrument(skip_all)]
pub fn new(
tab_snapshot: TabSnapshot,
font: Font,
@@ -131,6 +133,7 @@ impl WrapMap {
self.background_task.is_some()
}
+ #[ztracing::instrument(skip_all)]
pub fn sync(
&mut self,
tab_snapshot: TabSnapshot,
@@ -150,6 +153,7 @@ impl WrapMap {
(self.snapshot.clone(), mem::take(&mut self.edits_since_sync))
}
+ #[ztracing::instrument(skip_all)]
pub fn set_font_with_size(
&mut self,
font: Font,
@@ -167,6 +171,7 @@ impl WrapMap {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn set_wrap_width(&mut self, wrap_width: Option<Pixels>, cx: &mut Context<Self>) -> bool {
if wrap_width == self.wrap_width {
return false;
@@ -177,6 +182,7 @@ impl WrapMap {
true
}
+ #[ztracing::instrument(skip_all)]
fn rewrap(&mut self, cx: &mut Context<Self>) {
self.background_task.take();
self.interpolated_edits.clear();
@@ -248,6 +254,7 @@ impl WrapMap {
}
}
+ #[ztracing::instrument(skip_all)]
fn flush_edits(&mut self, cx: &mut Context<Self>) {
if !self.snapshot.interpolated {
let mut to_remove_len = 0;
@@ -330,6 +337,7 @@ impl WrapMap {
}
impl WrapSnapshot {
+ #[ztracing::instrument(skip_all)]
fn new(tab_snapshot: TabSnapshot) -> Self {
let mut transforms = SumTree::default();
let extent = tab_snapshot.text_summary();
@@ -343,10 +351,12 @@ impl WrapSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot {
self.tab_snapshot.buffer_snapshot()
}
+ #[ztracing::instrument(skip_all)]
fn interpolate(&mut self, new_tab_snapshot: TabSnapshot, tab_edits: &[TabEdit]) -> WrapPatch {
let mut new_transforms;
if tab_edits.is_empty() {
@@ -411,6 +421,7 @@ impl WrapSnapshot {
old_snapshot.compute_edits(tab_edits, self)
}
+ #[ztracing::instrument(skip_all)]
async fn update(
&mut self,
new_tab_snapshot: TabSnapshot,
@@ -570,6 +581,7 @@ impl WrapSnapshot {
old_snapshot.compute_edits(tab_edits, self)
}
+ #[ztracing::instrument(skip_all)]
fn compute_edits(&self, tab_edits: &[TabEdit], new_snapshot: &WrapSnapshot) -> WrapPatch {
let mut wrap_edits = Vec::with_capacity(tab_edits.len());
let mut old_cursor = self.transforms.cursor::<TransformSummary>(());
@@ -606,6 +618,7 @@ impl WrapSnapshot {
Patch::new(wrap_edits)
}
+ #[ztracing::instrument(skip_all)]
pub(crate) fn chunks<'a>(
&'a self,
rows: Range<WrapRow>,
@@ -640,10 +653,12 @@ impl WrapSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn max_point(&self) -> WrapPoint {
WrapPoint(self.transforms.summary().output.lines)
}
+ #[ztracing::instrument(skip_all)]
pub fn line_len(&self, row: WrapRow) -> u32 {
let (start, _, item) = self.transforms.find::<Dimensions<WrapPoint, TabPoint>, _>(
(),
@@ -664,6 +679,7 @@ impl WrapSnapshot {
}
}
+ #[ztracing::instrument(skip_all, fields(rows))]
pub fn text_summary_for_range(&self, rows: Range<WrapRow>) -> TextSummary {
let mut summary = TextSummary::default();
@@ -725,6 +741,7 @@ impl WrapSnapshot {
summary
}
+ #[ztracing::instrument(skip_all)]
pub fn soft_wrap_indent(&self, row: WrapRow) -> Option<u32> {
let (.., item) = self.transforms.find::<WrapPoint, _>(
(),
@@ -740,10 +757,12 @@ impl WrapSnapshot {
})
}
+ #[ztracing::instrument(skip_all)]
pub fn longest_row(&self) -> u32 {
self.transforms.summary().output.longest_row
}
+ #[ztracing::instrument(skip_all)]
pub fn row_infos(&self, start_row: WrapRow) -> WrapRows<'_> {
let mut transforms = self
.transforms
@@ -766,6 +785,7 @@ impl WrapSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn to_tab_point(&self, point: WrapPoint) -> TabPoint {
let (start, _, item) =
self.transforms
@@ -777,15 +797,18 @@ impl WrapSnapshot {
TabPoint(tab_point)
}
+ #[ztracing::instrument(skip_all)]
pub fn to_point(&self, point: WrapPoint, bias: Bias) -> Point {
self.tab_snapshot
.tab_point_to_point(self.to_tab_point(point), bias)
}
+ #[ztracing::instrument(skip_all)]
pub fn make_wrap_point(&self, point: Point, bias: Bias) -> WrapPoint {
self.tab_point_to_wrap_point(self.tab_snapshot.point_to_tab_point(point, bias))
}
+ #[ztracing::instrument(skip_all)]
pub fn tab_point_to_wrap_point(&self, point: TabPoint) -> WrapPoint {
let (start, ..) =
self.transforms
@@ -793,6 +816,7 @@ impl WrapSnapshot {
WrapPoint(start.1.0 + (point.0 - start.0.0))
}
+ #[ztracing::instrument(skip_all)]
pub fn wrap_point_cursor(&self) -> WrapPointCursor<'_> {
WrapPointCursor {
cursor: self
@@ -801,6 +825,7 @@ impl WrapSnapshot {
}
}
+ #[ztracing::instrument(skip_all)]
pub fn clip_point(&self, mut point: WrapPoint, bias: Bias) -> WrapPoint {
if bias == Bias::Left {
let (start, _, item) = self
@@ -815,6 +840,7 @@ impl WrapSnapshot {
self.tab_point_to_wrap_point(self.tab_snapshot.clip_point(self.to_tab_point(point), bias))
}
+ #[ztracing::instrument(skip_all, fields(point, ret))]
pub fn prev_row_boundary(&self, mut point: WrapPoint) -> WrapRow {
if self.transforms.is_empty() {
return WrapRow(0);
@@ -841,6 +867,7 @@ impl WrapSnapshot {
unreachable!()
}
+ #[ztracing::instrument(skip_all)]
pub fn next_row_boundary(&self, mut point: WrapPoint) -> Option<WrapRow> {
point.0 += Point::new(1, 0);
@@ -860,11 +887,13 @@ impl WrapSnapshot {
}
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub fn text(&self) -> String {
self.text_chunks(WrapRow(0)).collect()
}
#[cfg(test)]
+ #[ztracing::instrument(skip_all)]
pub fn text_chunks(&self, wrap_row: WrapRow) -> impl Iterator<Item = &str> {
self.chunks(
wrap_row..self.max_point().row() + WrapRow(1),
@@ -874,6 +903,7 @@ impl WrapSnapshot {
.map(|h| h.text)
}
+ #[ztracing::instrument(skip_all)]
fn check_invariants(&self) {
#[cfg(test)]
{
@@ -927,6 +957,7 @@ pub struct WrapPointCursor<'transforms> {
}
impl WrapPointCursor<'_> {
+ #[ztracing::instrument(skip_all)]
pub fn map(&mut self, point: TabPoint) -> WrapPoint {
let cursor = &mut self.cursor;
if cursor.did_seek() {
@@ -939,6 +970,7 @@ impl WrapPointCursor<'_> {
}
impl WrapChunks<'_> {
+ #[ztracing::instrument(skip_all)]
pub(crate) fn seek(&mut self, rows: Range<WrapRow>) {
let output_start = WrapPoint::new(rows.start, 0);
let output_end = WrapPoint::new(rows.end, 0);
@@ -961,6 +993,7 @@ impl WrapChunks<'_> {
impl<'a> Iterator for WrapChunks<'a> {
type Item = Chunk<'a>;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
if self.output_position.row() >= self.max_output_row {
return None;
@@ -1033,6 +1066,7 @@ impl<'a> Iterator for WrapChunks<'a> {
impl Iterator for WrapRows<'_> {
type Item = RowInfo;
+ #[ztracing::instrument(skip_all)]
fn next(&mut self) -> Option<Self::Item> {
if self.output_row > self.max_output_row {
return None;
@@ -1069,6 +1103,7 @@ impl Iterator for WrapRows<'_> {
}
impl Transform {
+ #[ztracing::instrument(skip_all)]
fn isomorphic(summary: TextSummary) -> Self {
#[cfg(test)]
assert!(!summary.lines.is_zero());
@@ -1082,6 +1117,7 @@ impl Transform {
}
}
+ #[ztracing::instrument(skip_all)]
fn wrap(indent: u32) -> Self {
static WRAP_TEXT: LazyLock<String> = LazyLock::new(|| {
let mut wrap_text = String::new();
@@ -1134,6 +1170,7 @@ trait SumTreeExt {
}
impl SumTreeExt for SumTree<Transform> {
+ #[ztracing::instrument(skip_all)]
fn push_or_extend(&mut self, transform: Transform) {
let mut transform = Some(transform);
self.update_last(
@@ -1197,6 +1234,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for TabPoint {
}
impl sum_tree::SeekTarget<'_, TransformSummary, TransformSummary> for TabPoint {
+ #[ztracing::instrument(skip_all)]
fn cmp(&self, cursor_location: &TransformSummary, _: ()) -> std::cmp::Ordering {
Ord::cmp(&self.0, &cursor_location.input.lines)
}
@@ -13,7 +13,6 @@ name = "git_ui"
path = "src/git_ui.rs"
[features]
-default = []
test-support = ["multi_buffer/test-support"]
[dependencies]
@@ -62,7 +61,8 @@ watch.workspace = true
workspace.workspace = true
zed_actions.workspace = true
zeroize.workspace = true
-
+ztracing.workspace = true
+tracing.workspace = true
[target.'cfg(windows)'.dependencies]
windows.workspace = true
@@ -78,3 +78,6 @@ settings = { workspace = true, features = ["test-support"] }
unindent.workspace = true
workspace = { workspace = true, features = ["test-support"] }
zlog.workspace = true
+
+[package.metadata.cargo-machete]
+ignored = ["tracing"]
@@ -46,6 +46,7 @@ use workspace::{
notifications::NotifyTaskExt,
searchable::SearchableItemHandle,
};
+use ztracing::instrument;
actions!(
git,
@@ -469,6 +470,7 @@ impl ProjectDiff {
}
}
+ #[instrument(skip_all)]
fn register_buffer(
&mut self,
path_key: PathKey,
@@ -42,6 +42,8 @@ sum_tree.workspace = true
text.workspace = true
theme.workspace = true
tree-sitter.workspace = true
+ztracing.workspace = true
+tracing.workspace = true
util.workspace = true
[dev-dependencies]
@@ -56,3 +58,6 @@ settings = { workspace = true, features = ["test-support"] }
text = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
zlog.workspace = true
+
+[package.metadata.cargo-machete]
+ignored = ["tracing"]
@@ -57,6 +57,7 @@ use text::{
};
use theme::SyntaxTheme;
use util::post_inc;
+use ztracing::instrument;
pub use self::path_key::PathKey;
@@ -1671,6 +1672,7 @@ impl MultiBuffer {
self.insert_excerpts_after(ExcerptId::max(), buffer, ranges, cx)
}
+ #[instrument(skip_all)]
fn merge_excerpt_ranges<'a>(
expanded_ranges: impl IntoIterator<Item = &'a ExcerptRange<Point>> + 'a,
) -> (Vec<ExcerptRange<Point>>, Vec<usize>) {
@@ -4483,6 +4485,7 @@ impl MultiBufferSnapshot {
self.convert_dimension(point, text::BufferSnapshot::point_utf16_to_point)
}
+ #[instrument(skip_all)]
pub fn point_to_offset(&self, point: Point) -> MultiBufferOffset {
self.convert_dimension(point, text::BufferSnapshot::point_to_offset)
}
@@ -4536,6 +4539,7 @@ impl MultiBufferSnapshot {
}
}
+ #[instrument(skip_all)]
fn convert_dimension<MBR1, MBR2, BR1, BR2>(
&self,
key: MBR1,
@@ -6684,6 +6688,7 @@ where
MBD: MultiBufferDimension + Ord + Sub + ops::AddAssign<<MBD as Sub>::Output>,
BD: TextDimension + AddAssign<<MBD as Sub>::Output>,
{
+ #[instrument(skip_all)]
fn seek(&mut self, position: &MBD) {
let position = OutputDimension(*position);
self.cached_region.take();
@@ -1,435 +1,437 @@
-use std::{mem, ops::Range, sync::Arc};
-
-use collections::HashSet;
-use gpui::{App, AppContext, Context, Entity};
-use itertools::Itertools;
-use language::{Buffer, BufferSnapshot};
-use rope::Point;
-use text::{Bias, BufferId, OffsetRangeExt, locator::Locator};
-use util::{post_inc, rel_path::RelPath};
-
-use crate::{
- Anchor, ExcerptId, ExcerptRange, ExpandExcerptDirection, MultiBuffer, build_excerpt_ranges,
-};
-
-#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Hash, Debug)]
-pub struct PathKey {
- // Used by the derived PartialOrd & Ord
- pub sort_prefix: Option<u64>,
- pub path: Arc<RelPath>,
-}
-
-impl PathKey {
- pub fn with_sort_prefix(sort_prefix: u64, path: Arc<RelPath>) -> Self {
- Self {
- sort_prefix: Some(sort_prefix),
- path,
- }
- }
-
- pub fn for_buffer(buffer: &Entity<Buffer>, cx: &App) -> Self {
- if let Some(file) = buffer.read(cx).file() {
- Self::with_sort_prefix(file.worktree_id(cx).to_proto(), file.path().clone())
- } else {
- Self {
- sort_prefix: None,
- path: RelPath::unix(&buffer.entity_id().to_string())
- .unwrap()
- .into_arc(),
- }
- }
- }
-}
-
-impl MultiBuffer {
- pub fn paths(&self) -> impl Iterator<Item = PathKey> + '_ {
- self.excerpts_by_path.keys().cloned()
- }
-
- pub fn remove_excerpts_for_path(&mut self, path: PathKey, cx: &mut Context<Self>) {
- if let Some(to_remove) = self.excerpts_by_path.remove(&path) {
- self.remove_excerpts(to_remove, cx)
- }
- if let Some(follower) = &self.follower {
- follower.update(cx, |follower, cx| {
- follower.remove_excerpts_for_path(path, cx);
- });
- }
- }
-
- pub fn location_for_path(&self, path: &PathKey, cx: &App) -> Option<Anchor> {
- let excerpt_id = self.excerpts_by_path.get(path)?.first()?;
- let snapshot = self.read(cx);
- let excerpt = snapshot.excerpt(*excerpt_id)?;
- Some(Anchor::in_buffer(excerpt.id, excerpt.range.context.start))
- }
-
- pub fn excerpt_paths(&self) -> impl Iterator<Item = &PathKey> {
- self.excerpts_by_path.keys()
- }
-
- /// Sets excerpts, returns `true` if at least one new excerpt was added.
- pub fn set_excerpts_for_path(
- &mut self,
- path: PathKey,
- buffer: Entity<Buffer>,
- ranges: impl IntoIterator<Item = Range<Point>>,
- context_line_count: u32,
- cx: &mut Context<Self>,
- ) -> (Vec<Range<Anchor>>, bool) {
- let buffer_snapshot = buffer.read(cx).snapshot();
- let excerpt_ranges = build_excerpt_ranges(ranges, context_line_count, &buffer_snapshot);
-
- let (new, counts) = Self::merge_excerpt_ranges(&excerpt_ranges);
- self.set_merged_excerpt_ranges_for_path(
- path,
- buffer,
- excerpt_ranges,
- &buffer_snapshot,
- new,
- counts,
- cx,
- )
- }
-
- pub fn set_excerpt_ranges_for_path(
- &mut self,
- path: PathKey,
- buffer: Entity<Buffer>,
- buffer_snapshot: &BufferSnapshot,
- excerpt_ranges: Vec<ExcerptRange<Point>>,
- cx: &mut Context<Self>,
- ) -> (Vec<Range<Anchor>>, bool) {
- let (new, counts) = Self::merge_excerpt_ranges(&excerpt_ranges);
- self.set_merged_excerpt_ranges_for_path(
- path,
- buffer,
- excerpt_ranges,
- buffer_snapshot,
- new,
- counts,
- cx,
- )
- }
-
- pub fn set_anchored_excerpts_for_path(
- &self,
- path_key: PathKey,
- buffer: Entity<Buffer>,
- ranges: Vec<Range<text::Anchor>>,
- context_line_count: u32,
- cx: &Context<Self>,
- ) -> impl Future<Output = Vec<Range<Anchor>>> + use<> {
- let buffer_snapshot = buffer.read(cx).snapshot();
- let multi_buffer = cx.weak_entity();
- let mut app = cx.to_async();
- async move {
- let snapshot = buffer_snapshot.clone();
- let (excerpt_ranges, new, counts) = app
- .background_spawn(async move {
- let ranges = ranges.into_iter().map(|range| range.to_point(&snapshot));
- let excerpt_ranges =
- build_excerpt_ranges(ranges, context_line_count, &snapshot);
- let (new, counts) = Self::merge_excerpt_ranges(&excerpt_ranges);
- (excerpt_ranges, new, counts)
- })
- .await;
-
- multi_buffer
- .update(&mut app, move |multi_buffer, cx| {
- let (ranges, _) = multi_buffer.set_merged_excerpt_ranges_for_path(
- path_key,
- buffer,
- excerpt_ranges,
- &buffer_snapshot,
- new,
- counts,
- cx,
- );
- ranges
- })
- .ok()
- .unwrap_or_default()
- }
- }
-
- pub fn remove_excerpts_for_buffer(&mut self, buffer: BufferId, cx: &mut Context<Self>) {
- self.remove_excerpts(
- self.excerpts_for_buffer(buffer, cx)
- .into_iter()
- .map(|(excerpt, _)| excerpt),
- cx,
- );
- }
-
- pub(super) fn expand_excerpts_with_paths(
- &mut self,
- ids: impl IntoIterator<Item = ExcerptId>,
- line_count: u32,
- direction: ExpandExcerptDirection,
- cx: &mut Context<Self>,
- ) {
- let grouped = ids
- .into_iter()
- .chunk_by(|id| self.paths_by_excerpt.get(id).cloned())
- .into_iter()
- .filter_map(|(k, v)| Some((k?, v.into_iter().collect::<Vec<_>>())))
- .collect::<Vec<_>>();
- let snapshot = self.snapshot(cx);
-
- for (path, ids) in grouped.into_iter() {
- let Some(excerpt_ids) = self.excerpts_by_path.get(&path) else {
- continue;
- };
-
- let ids_to_expand = HashSet::from_iter(ids);
- let mut excerpt_id_ = None;
- let expanded_ranges = excerpt_ids.iter().filter_map(|excerpt_id| {
- let excerpt = snapshot.excerpt(*excerpt_id)?;
- let excerpt_id = excerpt.id;
- if excerpt_id_.is_none() {
- excerpt_id_ = Some(excerpt_id);
- }
-
- let mut context = excerpt.range.context.to_point(&excerpt.buffer);
- if ids_to_expand.contains(&excerpt_id) {
- match direction {
- ExpandExcerptDirection::Up => {
- context.start.row = context.start.row.saturating_sub(line_count);
- context.start.column = 0;
- }
- ExpandExcerptDirection::Down => {
- context.end.row =
- (context.end.row + line_count).min(excerpt.buffer.max_point().row);
- context.end.column = excerpt.buffer.line_len(context.end.row);
- }
- ExpandExcerptDirection::UpAndDown => {
- context.start.row = context.start.row.saturating_sub(line_count);
- context.start.column = 0;
- context.end.row =
- (context.end.row + line_count).min(excerpt.buffer.max_point().row);
- context.end.column = excerpt.buffer.line_len(context.end.row);
- }
- }
- }
-
- Some(ExcerptRange {
- context,
- primary: excerpt.range.primary.to_point(&excerpt.buffer),
- })
- });
- let mut merged_ranges: Vec<ExcerptRange<Point>> = Vec::new();
- for range in expanded_ranges {
- if let Some(last_range) = merged_ranges.last_mut()
- && last_range.context.end >= range.context.start
- {
- last_range.context.end = range.context.end;
- continue;
- }
- merged_ranges.push(range)
- }
- let Some(excerpt_id) = excerpt_id_ else {
- continue;
- };
- let Some(buffer_id) = &snapshot.buffer_id_for_excerpt(excerpt_id) else {
- continue;
- };
-
- let Some(buffer) = self.buffers.get(buffer_id).map(|b| b.buffer.clone()) else {
- continue;
- };
-
- let buffer_snapshot = buffer.read(cx).snapshot();
- self.update_path_excerpts(path.clone(), buffer, &buffer_snapshot, merged_ranges, cx);
- }
- }
-
- /// Sets excerpts, returns `true` if at least one new excerpt was added.
- fn set_merged_excerpt_ranges_for_path(
- &mut self,
- path: PathKey,
- buffer: Entity<Buffer>,
- ranges: Vec<ExcerptRange<Point>>,
- buffer_snapshot: &BufferSnapshot,
- new: Vec<ExcerptRange<Point>>,
- counts: Vec<usize>,
- cx: &mut Context<Self>,
- ) -> (Vec<Range<Anchor>>, bool) {
- let (excerpt_ids, added_a_new_excerpt) =
- self.update_path_excerpts(path, buffer, buffer_snapshot, new, cx);
-
- let mut result = Vec::new();
- let mut ranges = ranges.into_iter();
- for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(counts.into_iter()) {
- for range in ranges.by_ref().take(range_count) {
- let range = Anchor::range_in_buffer(
- excerpt_id,
- buffer_snapshot.anchor_before(&range.primary.start)
- ..buffer_snapshot.anchor_after(&range.primary.end),
- );
- result.push(range)
- }
- }
- (result, added_a_new_excerpt)
- }
-
- fn update_path_excerpts(
- &mut self,
- path: PathKey,
- buffer: Entity<Buffer>,
- buffer_snapshot: &BufferSnapshot,
- new: Vec<ExcerptRange<Point>>,
- cx: &mut Context<Self>,
- ) -> (Vec<ExcerptId>, bool) {
- let mut insert_after = self
- .excerpts_by_path
- .range(..path.clone())
- .next_back()
- .and_then(|(_, value)| value.last().copied())
- .unwrap_or(ExcerptId::min());
-
- let existing = self
- .excerpts_by_path
- .get(&path)
- .cloned()
- .unwrap_or_default();
- let mut new_iter = new.into_iter().peekable();
- let mut existing_iter = existing.into_iter().peekable();
-
- let mut excerpt_ids = Vec::new();
- let mut to_remove = Vec::new();
- let mut to_insert: Vec<(ExcerptId, ExcerptRange<Point>)> = Vec::new();
- let mut added_a_new_excerpt = false;
- let snapshot = self.snapshot(cx);
-
- let mut next_excerpt_id =
- // is this right? What if we remove the last excerpt, then we might reallocate with a wrong mapping?
- if let Some(last_entry) = self.snapshot.borrow().excerpt_ids.last() {
- last_entry.id.0 + 1
- } else {
- 1
- };
-
- let mut next_excerpt_id = move || ExcerptId(post_inc(&mut next_excerpt_id));
-
- let mut excerpts_cursor = snapshot.excerpts.cursor::<Option<&Locator>>(());
- excerpts_cursor.next();
-
- loop {
- let existing = if let Some(&existing_id) = existing_iter.peek() {
- let locator = snapshot.excerpt_locator_for_id(existing_id);
- excerpts_cursor.seek_forward(&Some(locator), Bias::Left);
- if let Some(excerpt) = excerpts_cursor.item() {
- if excerpt.buffer_id != buffer_snapshot.remote_id() {
- to_remove.push(existing_id);
- existing_iter.next();
- continue;
- }
- Some((existing_id, excerpt.range.context.to_point(buffer_snapshot)))
- } else {
- None
- }
- } else {
- None
- };
-
- let new = new_iter.peek();
- if let Some((last_id, last)) = to_insert.last_mut() {
- if let Some(new) = new
- && last.context.end >= new.context.start
- {
- last.context.end = last.context.end.max(new.context.end);
- excerpt_ids.push(*last_id);
- new_iter.next();
- continue;
- }
- if let Some((existing_id, existing_range)) = &existing
- && last.context.end >= existing_range.start
- {
- last.context.end = last.context.end.max(existing_range.end);
- to_remove.push(*existing_id);
- self.snapshot
- .get_mut()
- .replaced_excerpts
- .insert(*existing_id, *last_id);
- existing_iter.next();
- continue;
- }
- }
-
- match (new, existing) {
- (None, None) => break,
- (None, Some((existing_id, _))) => {
- existing_iter.next();
- to_remove.push(existing_id);
- continue;
- }
- (Some(_), None) => {
- added_a_new_excerpt = true;
- let new_id = next_excerpt_id();
- excerpt_ids.push(new_id);
- to_insert.push((new_id, new_iter.next().unwrap()));
- continue;
- }
- (Some(new), Some((_, existing_range))) => {
- if existing_range.end < new.context.start {
- let existing_id = existing_iter.next().unwrap();
- to_remove.push(existing_id);
- continue;
- } else if existing_range.start > new.context.end {
- let new_id = next_excerpt_id();
- excerpt_ids.push(new_id);
- to_insert.push((new_id, new_iter.next().unwrap()));
- continue;
- }
-
- if existing_range.start == new.context.start
- && existing_range.end == new.context.end
- {
- self.insert_excerpts_with_ids_after(
- insert_after,
- buffer.clone(),
- mem::take(&mut to_insert),
- cx,
- );
- insert_after = existing_iter.next().unwrap();
- excerpt_ids.push(insert_after);
- new_iter.next();
- } else {
- let existing_id = existing_iter.next().unwrap();
- let new_id = next_excerpt_id();
- self.snapshot
- .get_mut()
- .replaced_excerpts
- .insert(existing_id, new_id);
- to_remove.push(existing_id);
- let mut range = new_iter.next().unwrap();
- range.context.start = range.context.start.min(existing_range.start);
- range.context.end = range.context.end.max(existing_range.end);
- excerpt_ids.push(new_id);
- to_insert.push((new_id, range));
- }
- }
- };
- }
-
- self.insert_excerpts_with_ids_after(insert_after, buffer, to_insert, cx);
- // todo(lw): There is a logic bug somewhere that causes the to_remove vector to be not ordered correctly
- to_remove.sort_by_cached_key(|&id| snapshot.excerpt_locator_for_id(id));
- self.remove_excerpts(to_remove, cx);
-
- if excerpt_ids.is_empty() {
- self.excerpts_by_path.remove(&path);
- } else {
- for excerpt_id in &excerpt_ids {
- self.paths_by_excerpt.insert(*excerpt_id, path.clone());
- }
- let snapshot = &*self.snapshot.get_mut();
- let mut excerpt_ids: Vec<_> = excerpt_ids.iter().dedup().cloned().collect();
- excerpt_ids.sort_by_cached_key(|&id| snapshot.excerpt_locator_for_id(id));
- self.excerpts_by_path.insert(path, excerpt_ids);
- }
-
- (excerpt_ids, added_a_new_excerpt)
- }
-}
+use std::{mem, ops::Range, sync::Arc};
+
+use collections::HashSet;
+use gpui::{App, AppContext, Context, Entity};
+use itertools::Itertools;
+use language::{Buffer, BufferSnapshot};
+use rope::Point;
+use text::{Bias, BufferId, OffsetRangeExt, locator::Locator};
+use util::{post_inc, rel_path::RelPath};
+use ztracing::instrument;
+
+use crate::{
+ Anchor, ExcerptId, ExcerptRange, ExpandExcerptDirection, MultiBuffer, build_excerpt_ranges,
+};
+
+#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Hash, Debug)]
+pub struct PathKey {
+ // Used by the derived PartialOrd & Ord
+ pub sort_prefix: Option<u64>,
+ pub path: Arc<RelPath>,
+}
+
+impl PathKey {
+ pub fn with_sort_prefix(sort_prefix: u64, path: Arc<RelPath>) -> Self {
+ Self {
+ sort_prefix: Some(sort_prefix),
+ path,
+ }
+ }
+
+ pub fn for_buffer(buffer: &Entity<Buffer>, cx: &App) -> Self {
+ if let Some(file) = buffer.read(cx).file() {
+ Self::with_sort_prefix(file.worktree_id(cx).to_proto(), file.path().clone())
+ } else {
+ Self {
+ sort_prefix: None,
+ path: RelPath::unix(&buffer.entity_id().to_string())
+ .unwrap()
+ .into_arc(),
+ }
+ }
+ }
+}
+
+impl MultiBuffer {
+ pub fn paths(&self) -> impl Iterator<Item = PathKey> + '_ {
+ self.excerpts_by_path.keys().cloned()
+ }
+
+ pub fn remove_excerpts_for_path(&mut self, path: PathKey, cx: &mut Context<Self>) {
+ if let Some(to_remove) = self.excerpts_by_path.remove(&path) {
+ self.remove_excerpts(to_remove, cx)
+ }
+ if let Some(follower) = &self.follower {
+ follower.update(cx, |follower, cx| {
+ follower.remove_excerpts_for_path(path, cx);
+ });
+ }
+ }
+
+ pub fn location_for_path(&self, path: &PathKey, cx: &App) -> Option<Anchor> {
+ let excerpt_id = self.excerpts_by_path.get(path)?.first()?;
+ let snapshot = self.read(cx);
+ let excerpt = snapshot.excerpt(*excerpt_id)?;
+ Some(Anchor::in_buffer(excerpt.id, excerpt.range.context.start))
+ }
+
+ pub fn excerpt_paths(&self) -> impl Iterator<Item = &PathKey> {
+ self.excerpts_by_path.keys()
+ }
+
+ /// Sets excerpts, returns `true` if at least one new excerpt was added.
+ #[instrument(skip_all)]
+ pub fn set_excerpts_for_path(
+ &mut self,
+ path: PathKey,
+ buffer: Entity<Buffer>,
+ ranges: impl IntoIterator<Item = Range<Point>>,
+ context_line_count: u32,
+ cx: &mut Context<Self>,
+ ) -> (Vec<Range<Anchor>>, bool) {
+ let buffer_snapshot = buffer.read(cx).snapshot();
+ let excerpt_ranges = build_excerpt_ranges(ranges, context_line_count, &buffer_snapshot);
+
+ let (new, counts) = Self::merge_excerpt_ranges(&excerpt_ranges);
+ self.set_merged_excerpt_ranges_for_path(
+ path,
+ buffer,
+ excerpt_ranges,
+ &buffer_snapshot,
+ new,
+ counts,
+ cx,
+ )
+ }
+
+ pub fn set_excerpt_ranges_for_path(
+ &mut self,
+ path: PathKey,
+ buffer: Entity<Buffer>,
+ buffer_snapshot: &BufferSnapshot,
+ excerpt_ranges: Vec<ExcerptRange<Point>>,
+ cx: &mut Context<Self>,
+ ) -> (Vec<Range<Anchor>>, bool) {
+ let (new, counts) = Self::merge_excerpt_ranges(&excerpt_ranges);
+ self.set_merged_excerpt_ranges_for_path(
+ path,
+ buffer,
+ excerpt_ranges,
+ buffer_snapshot,
+ new,
+ counts,
+ cx,
+ )
+ }
+
+ pub fn set_anchored_excerpts_for_path(
+ &self,
+ path_key: PathKey,
+ buffer: Entity<Buffer>,
+ ranges: Vec<Range<text::Anchor>>,
+ context_line_count: u32,
+ cx: &Context<Self>,
+ ) -> impl Future<Output = Vec<Range<Anchor>>> + use<> {
+ let buffer_snapshot = buffer.read(cx).snapshot();
+ let multi_buffer = cx.weak_entity();
+ let mut app = cx.to_async();
+ async move {
+ let snapshot = buffer_snapshot.clone();
+ let (excerpt_ranges, new, counts) = app
+ .background_spawn(async move {
+ let ranges = ranges.into_iter().map(|range| range.to_point(&snapshot));
+ let excerpt_ranges =
+ build_excerpt_ranges(ranges, context_line_count, &snapshot);
+ let (new, counts) = Self::merge_excerpt_ranges(&excerpt_ranges);
+ (excerpt_ranges, new, counts)
+ })
+ .await;
+
+ multi_buffer
+ .update(&mut app, move |multi_buffer, cx| {
+ let (ranges, _) = multi_buffer.set_merged_excerpt_ranges_for_path(
+ path_key,
+ buffer,
+ excerpt_ranges,
+ &buffer_snapshot,
+ new,
+ counts,
+ cx,
+ );
+ ranges
+ })
+ .ok()
+ .unwrap_or_default()
+ }
+ }
+
+ pub fn remove_excerpts_for_buffer(&mut self, buffer: BufferId, cx: &mut Context<Self>) {
+ self.remove_excerpts(
+ self.excerpts_for_buffer(buffer, cx)
+ .into_iter()
+ .map(|(excerpt, _)| excerpt),
+ cx,
+ );
+ }
+
+ pub(super) fn expand_excerpts_with_paths(
+ &mut self,
+ ids: impl IntoIterator<Item = ExcerptId>,
+ line_count: u32,
+ direction: ExpandExcerptDirection,
+ cx: &mut Context<Self>,
+ ) {
+ let grouped = ids
+ .into_iter()
+ .chunk_by(|id| self.paths_by_excerpt.get(id).cloned())
+ .into_iter()
+ .filter_map(|(k, v)| Some((k?, v.into_iter().collect::<Vec<_>>())))
+ .collect::<Vec<_>>();
+ let snapshot = self.snapshot(cx);
+
+ for (path, ids) in grouped.into_iter() {
+ let Some(excerpt_ids) = self.excerpts_by_path.get(&path) else {
+ continue;
+ };
+
+ let ids_to_expand = HashSet::from_iter(ids);
+ let mut excerpt_id_ = None;
+ let expanded_ranges = excerpt_ids.iter().filter_map(|excerpt_id| {
+ let excerpt = snapshot.excerpt(*excerpt_id)?;
+ let excerpt_id = excerpt.id;
+ if excerpt_id_.is_none() {
+ excerpt_id_ = Some(excerpt_id);
+ }
+
+ let mut context = excerpt.range.context.to_point(&excerpt.buffer);
+ if ids_to_expand.contains(&excerpt_id) {
+ match direction {
+ ExpandExcerptDirection::Up => {
+ context.start.row = context.start.row.saturating_sub(line_count);
+ context.start.column = 0;
+ }
+ ExpandExcerptDirection::Down => {
+ context.end.row =
+ (context.end.row + line_count).min(excerpt.buffer.max_point().row);
+ context.end.column = excerpt.buffer.line_len(context.end.row);
+ }
+ ExpandExcerptDirection::UpAndDown => {
+ context.start.row = context.start.row.saturating_sub(line_count);
+ context.start.column = 0;
+ context.end.row =
+ (context.end.row + line_count).min(excerpt.buffer.max_point().row);
+ context.end.column = excerpt.buffer.line_len(context.end.row);
+ }
+ }
+ }
+
+ Some(ExcerptRange {
+ context,
+ primary: excerpt.range.primary.to_point(&excerpt.buffer),
+ })
+ });
+ let mut merged_ranges: Vec<ExcerptRange<Point>> = Vec::new();
+ for range in expanded_ranges {
+ if let Some(last_range) = merged_ranges.last_mut()
+ && last_range.context.end >= range.context.start
+ {
+ last_range.context.end = range.context.end;
+ continue;
+ }
+ merged_ranges.push(range)
+ }
+ let Some(excerpt_id) = excerpt_id_ else {
+ continue;
+ };
+ let Some(buffer_id) = &snapshot.buffer_id_for_excerpt(excerpt_id) else {
+ continue;
+ };
+
+ let Some(buffer) = self.buffers.get(buffer_id).map(|b| b.buffer.clone()) else {
+ continue;
+ };
+
+ let buffer_snapshot = buffer.read(cx).snapshot();
+ self.update_path_excerpts(path.clone(), buffer, &buffer_snapshot, merged_ranges, cx);
+ }
+ }
+
+ /// Sets excerpts, returns `true` if at least one new excerpt was added.
+ fn set_merged_excerpt_ranges_for_path(
+ &mut self,
+ path: PathKey,
+ buffer: Entity<Buffer>,
+ ranges: Vec<ExcerptRange<Point>>,
+ buffer_snapshot: &BufferSnapshot,
+ new: Vec<ExcerptRange<Point>>,
+ counts: Vec<usize>,
+ cx: &mut Context<Self>,
+ ) -> (Vec<Range<Anchor>>, bool) {
+ let (excerpt_ids, added_a_new_excerpt) =
+ self.update_path_excerpts(path, buffer, buffer_snapshot, new, cx);
+
+ let mut result = Vec::new();
+ let mut ranges = ranges.into_iter();
+ for (excerpt_id, range_count) in excerpt_ids.into_iter().zip(counts.into_iter()) {
+ for range in ranges.by_ref().take(range_count) {
+ let range = Anchor::range_in_buffer(
+ excerpt_id,
+ buffer_snapshot.anchor_before(&range.primary.start)
+ ..buffer_snapshot.anchor_after(&range.primary.end),
+ );
+ result.push(range)
+ }
+ }
+ (result, added_a_new_excerpt)
+ }
+
+ fn update_path_excerpts(
+ &mut self,
+ path: PathKey,
+ buffer: Entity<Buffer>,
+ buffer_snapshot: &BufferSnapshot,
+ new: Vec<ExcerptRange<Point>>,
+ cx: &mut Context<Self>,
+ ) -> (Vec<ExcerptId>, bool) {
+ let mut insert_after = self
+ .excerpts_by_path
+ .range(..path.clone())
+ .next_back()
+ .and_then(|(_, value)| value.last().copied())
+ .unwrap_or(ExcerptId::min());
+
+ let existing = self
+ .excerpts_by_path
+ .get(&path)
+ .cloned()
+ .unwrap_or_default();
+ let mut new_iter = new.into_iter().peekable();
+ let mut existing_iter = existing.into_iter().peekable();
+
+ let mut excerpt_ids = Vec::new();
+ let mut to_remove = Vec::new();
+ let mut to_insert: Vec<(ExcerptId, ExcerptRange<Point>)> = Vec::new();
+ let mut added_a_new_excerpt = false;
+ let snapshot = self.snapshot(cx);
+
+ let mut next_excerpt_id =
+ // is this right? What if we remove the last excerpt, then we might reallocate with a wrong mapping?
+ if let Some(last_entry) = self.snapshot.borrow().excerpt_ids.last() {
+ last_entry.id.0 + 1
+ } else {
+ 1
+ };
+
+ let mut next_excerpt_id = move || ExcerptId(post_inc(&mut next_excerpt_id));
+
+ let mut excerpts_cursor = snapshot.excerpts.cursor::<Option<&Locator>>(());
+ excerpts_cursor.next();
+
+ loop {
+ let existing = if let Some(&existing_id) = existing_iter.peek() {
+ let locator = snapshot.excerpt_locator_for_id(existing_id);
+ excerpts_cursor.seek_forward(&Some(locator), Bias::Left);
+ if let Some(excerpt) = excerpts_cursor.item() {
+ if excerpt.buffer_id != buffer_snapshot.remote_id() {
+ to_remove.push(existing_id);
+ existing_iter.next();
+ continue;
+ }
+ Some((existing_id, excerpt.range.context.to_point(buffer_snapshot)))
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+
+ let new = new_iter.peek();
+ if let Some((last_id, last)) = to_insert.last_mut() {
+ if let Some(new) = new
+ && last.context.end >= new.context.start
+ {
+ last.context.end = last.context.end.max(new.context.end);
+ excerpt_ids.push(*last_id);
+ new_iter.next();
+ continue;
+ }
+ if let Some((existing_id, existing_range)) = &existing
+ && last.context.end >= existing_range.start
+ {
+ last.context.end = last.context.end.max(existing_range.end);
+ to_remove.push(*existing_id);
+ self.snapshot
+ .get_mut()
+ .replaced_excerpts
+ .insert(*existing_id, *last_id);
+ existing_iter.next();
+ continue;
+ }
+ }
+
+ match (new, existing) {
+ (None, None) => break,
+ (None, Some((existing_id, _))) => {
+ existing_iter.next();
+ to_remove.push(existing_id);
+ continue;
+ }
+ (Some(_), None) => {
+ added_a_new_excerpt = true;
+ let new_id = next_excerpt_id();
+ excerpt_ids.push(new_id);
+ to_insert.push((new_id, new_iter.next().unwrap()));
+ continue;
+ }
+ (Some(new), Some((_, existing_range))) => {
+ if existing_range.end < new.context.start {
+ let existing_id = existing_iter.next().unwrap();
+ to_remove.push(existing_id);
+ continue;
+ } else if existing_range.start > new.context.end {
+ let new_id = next_excerpt_id();
+ excerpt_ids.push(new_id);
+ to_insert.push((new_id, new_iter.next().unwrap()));
+ continue;
+ }
+
+ if existing_range.start == new.context.start
+ && existing_range.end == new.context.end
+ {
+ self.insert_excerpts_with_ids_after(
+ insert_after,
+ buffer.clone(),
+ mem::take(&mut to_insert),
+ cx,
+ );
+ insert_after = existing_iter.next().unwrap();
+ excerpt_ids.push(insert_after);
+ new_iter.next();
+ } else {
+ let existing_id = existing_iter.next().unwrap();
+ let new_id = next_excerpt_id();
+ self.snapshot
+ .get_mut()
+ .replaced_excerpts
+ .insert(existing_id, new_id);
+ to_remove.push(existing_id);
+ let mut range = new_iter.next().unwrap();
+ range.context.start = range.context.start.min(existing_range.start);
+ range.context.end = range.context.end.max(existing_range.end);
+ excerpt_ids.push(new_id);
+ to_insert.push((new_id, range));
+ }
+ }
+ };
+ }
+
+ self.insert_excerpts_with_ids_after(insert_after, buffer, to_insert, cx);
+ // todo(lw): There is a logic bug somewhere that causes the to_remove vector to be not ordered correctly
+ to_remove.sort_by_cached_key(|&id| snapshot.excerpt_locator_for_id(id));
+ self.remove_excerpts(to_remove, cx);
+
+ if excerpt_ids.is_empty() {
+ self.excerpts_by_path.remove(&path);
+ } else {
+ for excerpt_id in &excerpt_ids {
+ self.paths_by_excerpt.insert(*excerpt_id, path.clone());
+ }
+ let snapshot = &*self.snapshot.get_mut();
+ let mut excerpt_ids: Vec<_> = excerpt_ids.iter().dedup().cloned().collect();
+ excerpt_ids.sort_by_cached_key(|&id| snapshot.excerpt_locator_for_id(id));
+ self.excerpts_by_path.insert(path, excerpt_ids);
+ }
+
+ (excerpt_ids, added_a_new_excerpt)
+ }
+}
@@ -91,6 +91,8 @@ which.workspace = true
worktree.workspace = true
zeroize.workspace = true
zlog.workspace = true
+ztracing.workspace = true
+tracing.workspace = true
[dev-dependencies]
client = { workspace = true, features = ["test-support"] }
@@ -113,3 +115,6 @@ snippet_provider = { workspace = true, features = ["test-support"] }
unindent.workspace = true
util = { workspace = true, features = ["test-support"] }
worktree = { workspace = true, features = ["test-support"] }
+
+[package.metadata.cargo-machete]
+ignored = ["tracing"]
@@ -14,6 +14,7 @@ use gpui::{
use language::Buffer;
use text::BufferId;
use util::ResultExt;
+use ztracing::instrument;
use crate::{
Project,
@@ -254,6 +255,7 @@ impl BranchDiff {
self.repo.as_ref()
}
+ #[instrument(skip_all)]
pub fn load_buffers(&mut self, cx: &mut Context<Self>) -> Vec<DiffBuffer> {
let mut output = Vec::default();
let Some(repo) = self.repo.clone() else {
@@ -318,6 +320,7 @@ impl BranchDiff {
output
}
+ #[instrument(skip_all)]
fn load_buffer(
branch_diff: Option<git::status::TreeDiffStatus>,
project_path: crate::ProjectPath,
@@ -18,6 +18,8 @@ rayon.workspace = true
sum_tree.workspace = true
unicode-segmentation.workspace = true
util.workspace = true
+ztracing.workspace = true
+tracing.workspace = true
[dev-dependencies]
ctor.workspace = true
@@ -30,3 +32,6 @@ zlog.workspace = true
[[bench]]
name = "rope_benchmark"
harness = false
+
+[package.metadata.cargo-machete]
+ignored = ["tracing"]
@@ -12,6 +12,7 @@ use std::{
str,
};
use sum_tree::{Bias, Dimension, Dimensions, SumTree};
+use ztracing::instrument;
pub use chunk::{Chunk, ChunkSlice};
pub use offset_utf16::OffsetUtf16;
@@ -428,6 +429,7 @@ impl Rope {
})
}
+ #[instrument(skip_all)]
pub fn point_to_offset(&self, point: Point) -> usize {
if point >= self.summary().lines {
return self.summary().len;
@@ -17,8 +17,13 @@ doctest = false
arrayvec = "0.7.1"
rayon.workspace = true
log.workspace = true
+ztracing.workspace = true
+tracing.workspace = true
[dev-dependencies]
ctor.workspace = true
rand.workspace = true
zlog.workspace = true
+
+[package.metadata.cargo-machete]
+ignored = ["tracing"]
@@ -1,6 +1,7 @@
use super::*;
use arrayvec::ArrayVec;
use std::{cmp::Ordering, mem, sync::Arc};
+use ztracing::instrument;
#[derive(Clone)]
struct StackEntry<'a, T: Item, D> {
@@ -211,6 +212,7 @@ where
}
#[track_caller]
+ #[instrument(skip_all)]
pub fn prev(&mut self) {
self.search_backward(|_| true)
}
@@ -394,6 +396,7 @@ where
{
/// Returns whether we found the item you were seeking for.
#[track_caller]
+ #[instrument(skip_all)]
pub fn seek<Target>(&mut self, pos: &Target, bias: Bias) -> bool
where
Target: SeekTarget<'a, T::Summary, D>,
@@ -408,6 +411,7 @@ where
///
/// If we did not seek before, use seek instead in that case.
#[track_caller]
+ #[instrument(skip_all)]
pub fn seek_forward<Target>(&mut self, pos: &Target, bias: Bias) -> bool
where
Target: SeekTarget<'a, T::Summary, D>,
@@ -449,6 +453,7 @@ where
/// Returns whether we found the item you were seeking for.
#[track_caller]
+ #[instrument(skip_all)]
fn seek_internal(
&mut self,
target: &dyn SeekTarget<'a, T::Summary, D>,
@@ -8,6 +8,7 @@ use std::marker::PhantomData;
use std::mem;
use std::{cmp::Ordering, fmt, iter::FromIterator, sync::Arc};
pub use tree_map::{MapSeekTarget, TreeMap, TreeSet};
+use ztracing::instrument;
#[cfg(test)]
pub const TREE_BASE: usize = 2;
@@ -379,6 +380,7 @@ impl<T: Item> SumTree<T> {
/// A more efficient version of `Cursor::new()` + `Cursor::seek()` + `Cursor::item()`.
///
/// Only returns the item that exactly has the target match.
+ #[instrument(skip_all)]
pub fn find_exact<'a, 'slf, D, Target>(
&'slf self,
cx: <T::Summary as Summary>::Context<'a>,
@@ -404,6 +406,7 @@ impl<T: Item> SumTree<T> {
}
/// A more efficient version of `Cursor::new()` + `Cursor::seek()` + `Cursor::item()`
+ #[instrument(skip_all)]
pub fn find<'a, 'slf, D, Target>(
&'slf self,
cx: <T::Summary as Summary>::Context<'a>,
@@ -144,6 +144,8 @@ theme_extension.workspace = true
theme_selector.workspace = true
time.workspace = true
title_bar.workspace = true
+ztracing.workspace = true
+tracing.workspace = true
toolchain_selector.workspace = true
ui.workspace = true
ui_input.workspace = true
@@ -223,4 +225,4 @@ osx_info_plist_exts = ["resources/info/*"]
osx_url_schemes = ["zed"]
[package.metadata.cargo-machete]
-ignored = ["profiling", "zstd"]
+ignored = ["profiling", "zstd", "tracing"]
@@ -162,10 +162,11 @@ fn fail_to_open_window(e: anyhow::Error, _cx: &mut App) {
.detach();
}
}
-
pub static STARTUP_TIME: OnceLock<Instant> = OnceLock::new();
pub fn main() {
+ ztracing::init();
+
STARTUP_TIME.get_or_init(|| Instant::now());
#[cfg(unix)]
@@ -0,0 +1,17 @@
+[package]
+name = "ztracing"
+version = "0.1.0"
+edition.workspace = true
+publish.workspace = true
+license = "GPL-3.0-or-later"
+
+[lints]
+workspace = true
+
+[dependencies]
+tracing.workspace = true
+
+tracing-subscriber = "0.3.22"
+tracing-tracy = { workspace = true, features = ["enable", "ondemand"] }
+
+ztracing_macro.workspace = true
@@ -0,0 +1 @@
+../../LICENSE-AGPL
@@ -0,0 +1 @@
+../../LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-GPL
@@ -0,0 +1,9 @@
+use std::env;
+
+fn main() {
+ if env::var_os("ZTRACING").is_some() {
+ println!(r"cargo::rustc-cfg=ztracing");
+ }
+ println!("cargo::rerun-if-changed=build.rs");
+ println!("cargo::rerun-if-env-changed=ZTRACING");
+}
@@ -0,0 +1,16 @@
+#[cfg(ztracing)]
+pub use tracing::instrument;
+#[cfg(not(ztracing))]
+pub use ztracing_macro::instrument;
+
+#[cfg(ztracing)]
+pub fn init() {
+ use tracing_subscriber::prelude::*;
+ tracing::subscriber::set_global_default(
+ tracing_subscriber::registry().with(tracing_tracy::TracyLayer::default()),
+ )
+ .expect("setup tracy layer");
+}
+
+#[cfg(not(ztracing))]
+pub fn init() {}
@@ -0,0 +1,11 @@
+[package]
+name = "ztracing_macro"
+version = "0.1.0"
+edition.workspace = true
+publish.workspace = true
+license = "GPL-3.0-or-later"
+
+[lib]
+proc-macro = true
+
+[dependencies]
@@ -0,0 +1 @@
+../../LICENSE-AGPL
@@ -0,0 +1 @@
+../../LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-GPL
@@ -0,0 +1,7 @@
+#[proc_macro_attribute]
+pub fn instrument(
+ _attr: proc_macro::TokenStream,
+ item: proc_macro::TokenStream,
+) -> proc_macro::TokenStream {
+ item
+}
@@ -1,6 +1,6 @@
How to use our internal tools to profile and keep Zed fast.
-# Flamechart/CPU profiling
+# Rough quick CPU profiling (Flamechart)
See what the CPU spends the most time on. Strongly recommend you use
[samply](https://github.com/mstange/samply). It opens an interactive profile in
@@ -12,6 +12,46 @@ The profile.json does not contain any symbols. Firefox profiler can add the loca
<img width="851" height="613" alt="image" src="https://github.com/user-attachments/assets/cbef2b51-0442-4ee9-bc5c-95f6ccf9be2c" />
+# In depth CPU profiling (Tracing)
+
+See how long each annotated function call took and its arguments (if
+configured).
+
+Annotate any function you need appear in the profile with instrument. For more
+details see
+[tracing-instrument](https://docs.rs/tracing/latest/tracing/attr.instrument.html):
+
+```rust
+#[instrument(skip_all)]
+fn should_appear_in_profile(kitty: Cat) {
+ sleep(QUITE_LONG)
+}
+```
+
+Then either compile Zed with `ZTRACING=1 cargo r --release`. The release build is optional but highly recommended as like every program Zeds performance characteristics change dramatically with optimizations. You do not want to chase slowdowns that do not exist in release.
+
+## One time Setup/Building the profiler:
+
+Download the profiler:
+[linux x86_64](https://zed-tracy-import-miniprofiler.nyc3.digitaloceanspaces.com/tracy-profiler-linux-x86_64)
+[macos aarch64](https://zed-tracy-import-miniprofiler.nyc3.digitaloceanspaces.com/tracy-profiler-0.13.0-macos-aarch64)
+
+### Alternative: Building it yourself
+
+- Clone the repo at git@github.com:wolfpld/tracy.git
+- `cd profiler && mkdir build && cd build`
+- Run cmake to generate build files: `cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..`
+- Build the profiler: `ninja`
+- [Optional] move the profiler somewhere nice like ~/.local/bin on linux
+
+## Usage
+
+Open the profiler (tracy-profiler), you should see zed in the list of `Discovered clients` click it.
+<img width="392" height="287" alt="image" src="https://github.com/user-attachments/assets/b6f06fc3-6b25-41c7-ade9-558cc93d6033" />
+
+To find functions that take a long time follow this image:
+<img width="888" height="1159" alt="image" src="https://github.com/user-attachments/assets/77087617-f53a-4331-863d-e59f8a5b6f0b" />
+
# Task/Async profiling
Get a profile of the zed foreground executor and background executors. Check if
@@ -23,11 +63,17 @@ look at the results live.
## Setup/Building the importer:
+Download the importer
+[linux x86_64](https://zed-tracy-import-miniprofiler.nyc3.digitaloceanspaces.com/tracy-import-miniprofiler-linux-x86_64)
+[mac aarch64](https://zed-tracy-import-miniprofiler.nyc3.digitaloceanspaces.com/tracy-import-miniprofiler-macos-aarch64)
+
+### Alternative: Building it yourself
+
- Clone the repo at git@github.com:zed-industries/tracy.git on v0.12.2 branch
-- `cd profiler && mkdir build && cd build`
+- `cd import && mkdir build && cd build`
- Run cmake to generate build files: `cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..`
- Build the importer: `ninja`
-- Run the impoter on the trace file: `./tracy-import-miniprofiler /path/to/trace.miniprof /path/to/output.tracy`
+- Run the importer on the trace file: `./tracy-import-miniprofiler /path/to/trace.miniprof /path/to/output.tracy`
- Open the trace in tracy:
- If you're on windows download the v0.12.2 version from the releases on the upstream repo
- If you're on other platforms open it on the website: https://tracy.nereid.pl/ (the version might mismatch so your luck might vary, we need to host our own ideally..)