Support diagnostic navigation in multibuffers (#22620)
cc @nathansobo Release Notes: - Support diagnostic navigation in multibuffers
This commit is contained in:
parent
39af06085a
commit
11ec25aedb
13 changed files with 209 additions and 150 deletions
|
@ -99,8 +99,8 @@ use itertools::Itertools;
|
|||
use language::{
|
||||
language_settings::{self, all_language_settings, language_settings, InlayHintSettings},
|
||||
markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CharKind, CodeLabel,
|
||||
CursorShape, Diagnostic, Documentation, IndentKind, IndentSize, Language, OffsetRangeExt,
|
||||
Point, Selection, SelectionGoal, TransactionId,
|
||||
CursorShape, Diagnostic, DiagnosticEntry, Documentation, IndentKind, IndentSize, Language,
|
||||
OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
|
||||
};
|
||||
use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
|
||||
use linked_editing_ranges::refresh_linked_ranges;
|
||||
|
@ -3549,13 +3549,12 @@ impl Editor {
|
|||
Bias::Left,
|
||||
);
|
||||
let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
|
||||
multi_buffer
|
||||
.range_to_buffer_ranges(multi_buffer_visible_range, cx)
|
||||
multi_buffer_snapshot
|
||||
.range_to_buffer_ranges(multi_buffer_visible_range)
|
||||
.into_iter()
|
||||
.filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
|
||||
.filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
|
||||
let buffer = buffer_handle.read(cx);
|
||||
let buffer_file = project::File::from_dyn(buffer.file())?;
|
||||
.filter(|(_, excerpt_visible_range)| !excerpt_visible_range.is_empty())
|
||||
.filter_map(|(excerpt, excerpt_visible_range)| {
|
||||
let buffer_file = project::File::from_dyn(excerpt.buffer().file())?;
|
||||
let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
|
||||
let worktree_entry = buffer_worktree
|
||||
.read(cx)
|
||||
|
@ -3564,17 +3563,17 @@ impl Editor {
|
|||
return None;
|
||||
}
|
||||
|
||||
let language = buffer.language()?;
|
||||
let language = excerpt.buffer().language()?;
|
||||
if let Some(restrict_to_languages) = restrict_to_languages {
|
||||
if !restrict_to_languages.contains(language) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some((
|
||||
excerpt_id,
|
||||
excerpt.id(),
|
||||
(
|
||||
buffer_handle,
|
||||
buffer.version().clone(),
|
||||
multi_buffer.buffer(excerpt.buffer_id()).unwrap(),
|
||||
excerpt.buffer().version().clone(),
|
||||
excerpt_visible_range,
|
||||
),
|
||||
))
|
||||
|
@ -9179,10 +9178,23 @@ impl Editor {
|
|||
let snapshot = self.snapshot(cx);
|
||||
loop {
|
||||
let diagnostics = if direction == Direction::Prev {
|
||||
buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
|
||||
buffer
|
||||
.diagnostics_in_range(0..search_start, true)
|
||||
.map(|DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
|
||||
diagnostic,
|
||||
range: range.to_offset(&buffer),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
|
||||
buffer
|
||||
.diagnostics_in_range(search_start..buffer.len(), false)
|
||||
.map(|DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
|
||||
diagnostic,
|
||||
range: range.to_offset(&buffer),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
.into_iter()
|
||||
.filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start));
|
||||
let group = diagnostics
|
||||
// relies on diagnostics_in_range to return diagnostics with the same starting range to
|
||||
|
@ -10289,11 +10301,12 @@ impl Editor {
|
|||
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||
let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
|
||||
let is_valid = buffer
|
||||
.diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
|
||||
.diagnostics_in_range(active_diagnostics.primary_range.clone(), false)
|
||||
.any(|entry| {
|
||||
let range = entry.range.to_offset(&buffer);
|
||||
entry.diagnostic.is_primary
|
||||
&& !entry.range.is_empty()
|
||||
&& entry.range.start == primary_range_start
|
||||
&& !range.is_empty()
|
||||
&& range.start == primary_range_start
|
||||
&& entry.diagnostic.message == active_diagnostics.primary_message
|
||||
});
|
||||
|
||||
|
@ -11493,21 +11506,23 @@ impl Editor {
|
|||
let (buffer, selection) = if let Some(buffer) = self.buffer().read(cx).as_singleton() {
|
||||
(buffer, selection_range.start.row..selection_range.end.row)
|
||||
} else {
|
||||
let buffer_ranges = self
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.range_to_buffer_ranges(selection_range, cx);
|
||||
let multi_buffer = self.buffer().read(cx);
|
||||
let multi_buffer_snapshot = multi_buffer.snapshot(cx);
|
||||
let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
|
||||
|
||||
let (buffer, range, _) = if selection.reversed {
|
||||
let (excerpt, range) = if selection.reversed {
|
||||
buffer_ranges.first()
|
||||
} else {
|
||||
buffer_ranges.last()
|
||||
}?;
|
||||
|
||||
let snapshot = buffer.read(cx).snapshot();
|
||||
let snapshot = excerpt.buffer();
|
||||
let selection = text::ToPoint::to_point(&range.start, &snapshot).row
|
||||
..text::ToPoint::to_point(&range.end, &snapshot).row;
|
||||
(buffer.clone(), selection)
|
||||
(
|
||||
multi_buffer.buffer(excerpt.buffer_id()).unwrap().clone(),
|
||||
selection,
|
||||
)
|
||||
};
|
||||
|
||||
Some((buffer, selection))
|
||||
|
@ -12399,17 +12414,18 @@ impl Editor {
|
|||
};
|
||||
|
||||
let selections = self.selections.all::<usize>(cx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
let multi_buffer = self.buffer.read(cx);
|
||||
let multi_buffer_snapshot = multi_buffer.snapshot(cx);
|
||||
let mut new_selections_by_buffer = HashMap::default();
|
||||
for selection in selections {
|
||||
for (buffer, range, _) in
|
||||
buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
|
||||
for (excerpt, range) in
|
||||
multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
|
||||
{
|
||||
let mut range = range.to_point(buffer.read(cx));
|
||||
let mut range = range.to_point(excerpt.buffer());
|
||||
range.start.column = 0;
|
||||
range.end.column = buffer.read(cx).line_len(range.end.row);
|
||||
range.end.column = excerpt.buffer().line_len(range.end.row);
|
||||
new_selections_by_buffer
|
||||
.entry(buffer)
|
||||
.entry(multi_buffer.buffer(excerpt.buffer_id()).unwrap())
|
||||
.or_insert(Vec::new())
|
||||
.push(range)
|
||||
}
|
||||
|
@ -12508,13 +12524,15 @@ impl Editor {
|
|||
}
|
||||
None => {
|
||||
let selections = self.selections.all::<usize>(cx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
let multi_buffer = self.buffer.read(cx);
|
||||
for selection in selections {
|
||||
for (mut buffer_handle, mut range, _) in
|
||||
buffer.range_to_buffer_ranges(selection.range(), cx)
|
||||
for (excerpt, mut range) in multi_buffer
|
||||
.snapshot(cx)
|
||||
.range_to_buffer_ranges(selection.range())
|
||||
{
|
||||
// When editing branch buffers, jump to the corresponding location
|
||||
// in their base buffer.
|
||||
let mut buffer_handle = multi_buffer.buffer(excerpt.buffer_id()).unwrap();
|
||||
let buffer = buffer_handle.read(cx);
|
||||
if let Some(base_buffer) = buffer.base_buffer() {
|
||||
range = buffer.range_to_version(range, &base_buffer.read(cx).version());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue