Ensure path headers appear before first diagnostic header

Max Brunsfeld and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/diagnostics/src/diagnostics.rs      | 35 +++++++++++------------
crates/editor/src/display_map/block_map.rs | 14 +++++++--
2 files changed, 28 insertions(+), 21 deletions(-)

Detailed changes

crates/diagnostics/src/diagnostics.rs 🔗

@@ -423,28 +423,27 @@ impl ProjectDiagnosticsEditor {
                 render: path_header_renderer(buffer, self.build_settings.clone()),
                 disposition: BlockDisposition::Above,
             });
-            let mut block_ids = editor
-                .insert_blocks(
-                    header_block
-                        .into_iter()
-                        .chain(blocks_to_add.into_iter().map(|block| {
-                            let (excerpt_id, text_anchor) = block.position;
-                            BlockProperties {
-                                position: excerpts_snapshot
-                                    .anchor_in_excerpt(excerpt_id, text_anchor),
-                                height: block.height,
-                                render: block.render,
-                                disposition: block.disposition,
-                            }
-                        })),
-                    cx,
-                )
-                .into_iter();
+            let block_ids = editor.insert_blocks(
+                blocks_to_add
+                    .into_iter()
+                    .map(|block| {
+                        let (excerpt_id, text_anchor) = block.position;
+                        BlockProperties {
+                            position: excerpts_snapshot.anchor_in_excerpt(excerpt_id, text_anchor),
+                            height: block.height,
+                            render: block.render,
+                            disposition: block.disposition,
+                        }
+                    })
+                    .chain(header_block.into_iter()),
+                cx,
+            );
 
-            path_state.header = block_ids.next();
+            let mut block_ids = block_ids.into_iter();
             for group_state in &mut groups_to_add {
                 group_state.blocks = block_ids.by_ref().take(group_state.block_count).collect();
             }
+            path_state.header = block_ids.next();
         });
 
         for ix in group_ixs_to_remove.into_iter().rev() {

crates/editor/src/display_map/block_map.rs 🔗

@@ -5,7 +5,7 @@ use gpui::{AppContext, ElementBox};
 use language::Chunk;
 use parking_lot::Mutex;
 use std::{
-    cmp::{self, Ordering},
+    cmp::{self, Ordering, Reverse},
     fmt::Debug,
     ops::{Deref, Range},
     sync::{
@@ -276,7 +276,11 @@ impl BlockMap {
                         (position.row(), column, block.clone())
                     }),
             );
-            blocks_in_edit.sort_by_key(|(row, _, block)| (*row, block.disposition, block.id));
+
+            // When multiple blocks are on the same row, newer blocks appear above older
+            // blocks. This is arbitrary, but we currently rely on it in ProjectDiagnosticsEditor.
+            blocks_in_edit
+                .sort_by_key(|(row, _, block)| (*row, block.disposition, Reverse(block.id)));
 
             // For each of these blocks, insert a new isomorphic transform preceding the block,
             // and then insert the block itself.
@@ -940,7 +944,11 @@ mod tests {
                     start_row..start_row + block.height(),
                     block.column(),
                     block
-                        .render(&BlockContext { cx, anchor_x: 0., line_number_x: 0., })
+                        .render(&BlockContext {
+                            cx,
+                            anchor_x: 0.,
+                            line_number_x: 0.,
+                        })
                         .name()
                         .unwrap()
                         .to_string(),