Update block diagnostics (#28006)

Release Notes:

- "Block" diagnostics (that show up in the diagnostics view, or when
using `f8`/`shift-f8`) are rendered more clearly
- `f8`/`shift-f8` now always go to the "next" or "prev" diagnostic,
regardless of the state of the editor

![Screenshot 2025-04-09 at 16 42
09](https://github.com/user-attachments/assets/ae6d2ff6-5183-4b74-89d0-fefee1aa11e3)

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Co-authored-by: Julia Ryan <juliaryan3.14@gmail.com>
This commit is contained in:
Conrad Irwin 2025-04-15 09:35:13 -06:00 committed by GitHub
parent ccf9aef767
commit afabcd1547
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 1794 additions and 1987 deletions

View file

@ -1,11 +1,11 @@
use crate::{
BlockId, COLUMNAR_SELECTION_MODIFIERS, CURSORS_VISIBLE_FOR, ChunkRendererContext,
ChunkReplacement, ContextMenuPlacement, CursorShape, CustomBlockId, DisplayDiffHunk,
DisplayPoint, DisplayRow, DocumentHighlightRead, DocumentHighlightWrite, EditDisplayMode,
Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, FILE_HEADER_HEIGHT,
FocusedBlock, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor,
InlayHintRefreshReason, InlineCompletion, JumpData, LineDown, LineHighlight, LineUp,
MAX_LINE_LEN, MIN_LINE_NUMBER_DIGITS, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, OpenExcerpts,
ActiveDiagnostic, BlockId, COLUMNAR_SELECTION_MODIFIERS, CURSORS_VISIBLE_FOR,
ChunkRendererContext, ChunkReplacement, ContextMenuPlacement, CursorShape, CustomBlockId,
DisplayDiffHunk, DisplayPoint, DisplayRow, DocumentHighlightRead, DocumentHighlightWrite,
EditDisplayMode, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle,
FILE_HEADER_HEIGHT, FocusedBlock, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput,
HoveredCursor, InlayHintRefreshReason, InlineCompletion, JumpData, LineDown, LineHighlight,
LineUp, MAX_LINE_LEN, MIN_LINE_NUMBER_DIGITS, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, OpenExcerpts,
PageDown, PageUp, Point, RowExt, RowRangeExt, SelectPhase, SelectedTextHighlight, Selection,
SoftWrap, StickyHeaderExcerpt, ToPoint, ToggleFold,
code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP},
@ -1614,12 +1614,12 @@ impl EditorElement {
project_settings::DiagnosticSeverity::Hint => DiagnosticSeverity::HINT,
});
let active_diagnostics_group = self
.editor
.read(cx)
.active_diagnostics
.as_ref()
.map(|active_diagnostics| active_diagnostics.group_id);
let active_diagnostics_group =
if let ActiveDiagnostic::Group(group) = &self.editor.read(cx).active_diagnostics {
Some(group.group_id)
} else {
None
};
let diagnostics_by_rows = self.editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(window, cx);
@ -2643,12 +2643,15 @@ impl EditorElement {
sticky_header_excerpt_id: Option<ExcerptId>,
window: &mut Window,
cx: &mut App,
) -> (AnyElement, Size<Pixels>, DisplayRow, Pixels) {
) -> Option<(AnyElement, Size<Pixels>, DisplayRow, Pixels)> {
let mut x_position = None;
let mut element = match block {
Block::Custom(block) => {
let block_start = block.start().to_point(&snapshot.buffer_snapshot);
let block_end = block.end().to_point(&snapshot.buffer_snapshot);
Block::Custom(custom) => {
let block_start = custom.start().to_point(&snapshot.buffer_snapshot);
let block_end = custom.end().to_point(&snapshot.buffer_snapshot);
if block.place_near() && snapshot.is_line_folded(MultiBufferRow(block_start.row)) {
return None;
}
let align_to = block_start.to_display_point(snapshot);
let x_and_width = |layout: &LineWithInvisibles| {
Some((
@ -2686,7 +2689,7 @@ impl EditorElement {
div()
.size_full()
.child(block.render(&mut BlockContext {
.child(custom.render(&mut BlockContext {
window,
app: cx,
anchor_x,
@ -2774,6 +2777,7 @@ impl EditorElement {
} else {
element.layout_as_root(size(available_width, quantized_height.into()), window, cx)
};
let mut element_height_in_lines = ((final_size.height / line_height).ceil() as u32).max(1);
let mut row = block_row_start;
let mut x_offset = px(0.);
@ -2781,20 +2785,19 @@ impl EditorElement {
if let BlockId::Custom(custom_block_id) = block_id {
if block.has_height() {
let mut element_height_in_lines =
((final_size.height / line_height).ceil() as u32).max(1);
if block.place_near() && element_height_in_lines == 1 {
if block.place_near() {
if let Some((x_target, line_width)) = x_position {
let margin = em_width * 2;
if line_width + final_size.width + margin
< editor_width + gutter_dimensions.full_width()
&& !row_block_types.contains_key(&(row - 1))
&& element_height_in_lines == 1
{
x_offset = line_width + margin;
row = row - 1;
is_block = false;
element_height_in_lines = 0;
row_block_types.insert(row, is_block);
} else {
let max_offset =
editor_width + gutter_dimensions.full_width() - final_size.width;
@ -2809,9 +2812,11 @@ impl EditorElement {
}
}
}
row_block_types.insert(row, is_block);
for i in 0..element_height_in_lines {
row_block_types.insert(row + i, is_block);
}
(element, final_size, row, x_offset)
Some((element, final_size, row, x_offset))
}
fn render_buffer_header(
@ -3044,7 +3049,7 @@ impl EditorElement {
focused_block = None;
}
let (element, element_size, row, x_offset) = self.render_block(
if let Some((element, element_size, row, x_offset)) = self.render_block(
block,
AvailableSpace::MinContent,
block_id,
@ -3067,19 +3072,19 @@ impl EditorElement {
sticky_header_excerpt_id,
window,
cx,
);
fixed_block_max_width = fixed_block_max_width.max(element_size.width + em_width);
blocks.push(BlockLayout {
id: block_id,
x_offset,
row: Some(row),
element,
available_space: size(AvailableSpace::MinContent, element_size.height.into()),
style: BlockStyle::Fixed,
overlaps_gutter: true,
is_buffer_header: block.is_buffer_header(),
});
) {
fixed_block_max_width = fixed_block_max_width.max(element_size.width + em_width);
blocks.push(BlockLayout {
id: block_id,
x_offset,
row: Some(row),
element,
available_space: size(AvailableSpace::MinContent, element_size.height.into()),
style: BlockStyle::Fixed,
overlaps_gutter: true,
is_buffer_header: block.is_buffer_header(),
});
}
}
for (row, block) in non_fixed_blocks {
@ -3101,7 +3106,7 @@ impl EditorElement {
focused_block = None;
}
let (element, element_size, row, x_offset) = self.render_block(
if let Some((element, element_size, row, x_offset)) = self.render_block(
block,
width,
block_id,
@ -3124,18 +3129,18 @@ impl EditorElement {
sticky_header_excerpt_id,
window,
cx,
);
blocks.push(BlockLayout {
id: block_id,
x_offset,
row: Some(row),
element,
available_space: size(width, element_size.height.into()),
style,
overlaps_gutter: !block.place_near(),
is_buffer_header: block.is_buffer_header(),
});
) {
blocks.push(BlockLayout {
id: block_id,
x_offset,
row: Some(row),
element,
available_space: size(width, element_size.height.into()),
style,
overlaps_gutter: !block.place_near(),
is_buffer_header: block.is_buffer_header(),
});
}
}
if let Some(focused_block) = focused_block {
@ -3155,7 +3160,7 @@ impl EditorElement {
BlockStyle::Sticky => AvailableSpace::Definite(hitbox.size.width),
};
let (element, element_size, _, x_offset) = self.render_block(
if let Some((element, element_size, _, x_offset)) = self.render_block(
&block,
width,
focused_block.id,
@ -3178,18 +3183,18 @@ impl EditorElement {
sticky_header_excerpt_id,
window,
cx,
);
blocks.push(BlockLayout {
id: block.id(),
x_offset,
row: None,
element,
available_space: size(width, element_size.height.into()),
style,
overlaps_gutter: true,
is_buffer_header: block.is_buffer_header(),
});
) {
blocks.push(BlockLayout {
id: block.id(),
x_offset,
row: None,
element,
available_space: size(width, element_size.height.into()),
style,
overlaps_gutter: true,
is_buffer_header: block.is_buffer_header(),
});
}
}
}
}