Implement shift-f8
to go to previous diagnostic
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
a6d0caf557
commit
021699e51c
8 changed files with 74 additions and 35 deletions
|
@ -115,7 +115,7 @@ action!(ToggleComments);
|
||||||
action!(SelectLargerSyntaxNode);
|
action!(SelectLargerSyntaxNode);
|
||||||
action!(SelectSmallerSyntaxNode);
|
action!(SelectSmallerSyntaxNode);
|
||||||
action!(MoveToEnclosingBracket);
|
action!(MoveToEnclosingBracket);
|
||||||
action!(ShowNextDiagnostic);
|
action!(GoToDiagnostic, Direction);
|
||||||
action!(GoToDefinition);
|
action!(GoToDefinition);
|
||||||
action!(FindAllReferences);
|
action!(FindAllReferences);
|
||||||
action!(Rename);
|
action!(Rename);
|
||||||
|
@ -136,6 +136,12 @@ action!(OpenExcerpts);
|
||||||
enum DocumentHighlightRead {}
|
enum DocumentHighlightRead {}
|
||||||
enum DocumentHighlightWrite {}
|
enum DocumentHighlightWrite {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum Direction {
|
||||||
|
Prev,
|
||||||
|
Next,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) {
|
pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) {
|
||||||
path_openers.push(Box::new(items::BufferOpener));
|
path_openers.push(Box::new(items::BufferOpener));
|
||||||
cx.add_bindings(vec![
|
cx.add_bindings(vec![
|
||||||
|
@ -250,7 +256,8 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpene
|
||||||
Binding::new("ctrl-w", SelectLargerSyntaxNode, Some("Editor")),
|
Binding::new("ctrl-w", SelectLargerSyntaxNode, Some("Editor")),
|
||||||
Binding::new("alt-down", SelectSmallerSyntaxNode, Some("Editor")),
|
Binding::new("alt-down", SelectSmallerSyntaxNode, Some("Editor")),
|
||||||
Binding::new("ctrl-shift-W", SelectSmallerSyntaxNode, Some("Editor")),
|
Binding::new("ctrl-shift-W", SelectSmallerSyntaxNode, Some("Editor")),
|
||||||
Binding::new("f8", ShowNextDiagnostic, Some("Editor")),
|
Binding::new("f8", GoToDiagnostic(Direction::Next), Some("Editor")),
|
||||||
|
Binding::new("shift-f8", GoToDiagnostic(Direction::Prev), Some("Editor")),
|
||||||
Binding::new("f2", Rename, Some("Editor")),
|
Binding::new("f2", Rename, Some("Editor")),
|
||||||
Binding::new("f12", GoToDefinition, Some("Editor")),
|
Binding::new("f12", GoToDefinition, Some("Editor")),
|
||||||
Binding::new("alt-shift-f12", FindAllReferences, Some("Editor")),
|
Binding::new("alt-shift-f12", FindAllReferences, Some("Editor")),
|
||||||
|
@ -319,7 +326,7 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpene
|
||||||
cx.add_action(Editor::select_larger_syntax_node);
|
cx.add_action(Editor::select_larger_syntax_node);
|
||||||
cx.add_action(Editor::select_smaller_syntax_node);
|
cx.add_action(Editor::select_smaller_syntax_node);
|
||||||
cx.add_action(Editor::move_to_enclosing_bracket);
|
cx.add_action(Editor::move_to_enclosing_bracket);
|
||||||
cx.add_action(Editor::show_next_diagnostic);
|
cx.add_action(Editor::go_to_diagnostic);
|
||||||
cx.add_action(Editor::go_to_definition);
|
cx.add_action(Editor::go_to_definition);
|
||||||
cx.add_action(Editor::page_up);
|
cx.add_action(Editor::page_up);
|
||||||
cx.add_action(Editor::page_down);
|
cx.add_action(Editor::page_down);
|
||||||
|
@ -4173,7 +4180,11 @@ impl Editor {
|
||||||
self.update_selections(selections, Some(Autoscroll::Fit), cx);
|
self.update_selections(selections, Some(Autoscroll::Fit), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_next_diagnostic(&mut self, _: &ShowNextDiagnostic, cx: &mut ViewContext<Self>) {
|
pub fn go_to_diagnostic(
|
||||||
|
&mut self,
|
||||||
|
&GoToDiagnostic(direction): &GoToDiagnostic,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||||
let selection = self.newest_selection_with_snapshot::<usize>(&buffer);
|
let selection = self.newest_selection_with_snapshot::<usize>(&buffer);
|
||||||
let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
|
let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
|
||||||
|
@ -4193,9 +4204,12 @@ impl Editor {
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let next_group = buffer
|
let mut diagnostics = if direction == Direction::Prev {
|
||||||
.diagnostics_in_range::<_, usize>(search_start..buffer.len())
|
buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
|
||||||
.find_map(|entry| {
|
} else {
|
||||||
|
buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
|
||||||
|
};
|
||||||
|
let group = diagnostics.find_map(|entry| {
|
||||||
if entry.diagnostic.is_primary
|
if entry.diagnostic.is_primary
|
||||||
&& !entry.range.is_empty()
|
&& !entry.range.is_empty()
|
||||||
&& Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
|
&& Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
|
||||||
|
@ -4206,7 +4220,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some((primary_range, group_id)) = next_group {
|
if let Some((primary_range, group_id)) = group {
|
||||||
self.activate_diagnostics(group_id, cx);
|
self.activate_diagnostics(group_id, cx);
|
||||||
self.update_selections(
|
self.update_selections(
|
||||||
vec![Selection {
|
vec![Selection {
|
||||||
|
@ -4220,13 +4234,23 @@ impl Editor {
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
} else if search_start == 0 {
|
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
// Cycle around to the start of the buffer, potentially moving back to the start of
|
// Cycle around to the start of the buffer, potentially moving back to the start of
|
||||||
// the currently active diagnostic.
|
// the currently active diagnostic.
|
||||||
search_start = 0;
|
|
||||||
active_primary_range.take();
|
active_primary_range.take();
|
||||||
|
if direction == Direction::Prev {
|
||||||
|
if search_start == buffer.len() {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
search_start = buffer.len();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if search_start == 0 {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
search_start = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4590,7 +4614,7 @@ impl Editor {
|
||||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||||
let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
|
let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
|
||||||
let is_valid = buffer
|
let is_valid = buffer
|
||||||
.diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone())
|
.diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
|
||||||
.any(|entry| {
|
.any(|entry| {
|
||||||
entry.diagnostic.is_primary
|
entry.diagnostic.is_primary
|
||||||
&& !entry.range.is_empty()
|
&& !entry.range.is_empty()
|
||||||
|
|
|
@ -373,7 +373,7 @@ impl DiagnosticMessage {
|
||||||
.head();
|
.head();
|
||||||
let new_diagnostic = buffer
|
let new_diagnostic = buffer
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.diagnostics_in_range::<_, usize>(cursor_position..cursor_position)
|
.diagnostics_in_range::<_, usize>(cursor_position..cursor_position, false)
|
||||||
.filter(|entry| !entry.range.is_empty())
|
.filter(|entry| !entry.range.is_empty())
|
||||||
.min_by_key(|entry| (entry.diagnostic.severity, entry.range.len()))
|
.min_by_key(|entry| (entry.diagnostic.severity, entry.range.len()))
|
||||||
.map(|entry| entry.diagnostic);
|
.map(|entry| entry.diagnostic);
|
||||||
|
|
|
@ -2179,6 +2179,7 @@ impl MultiBufferSnapshot {
|
||||||
pub fn diagnostics_in_range<'a, T, O>(
|
pub fn diagnostics_in_range<'a, T, O>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<T>,
|
range: Range<T>,
|
||||||
|
reversed: bool,
|
||||||
) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
|
) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
|
||||||
where
|
where
|
||||||
T: 'a + ToOffset,
|
T: 'a + ToOffset,
|
||||||
|
@ -2187,7 +2188,10 @@ impl MultiBufferSnapshot {
|
||||||
self.as_singleton()
|
self.as_singleton()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(move |(_, _, buffer)| {
|
.flat_map(move |(_, _, buffer)| {
|
||||||
buffer.diagnostics_in_range(range.start.to_offset(self)..range.end.to_offset(self))
|
buffer.diagnostics_in_range(
|
||||||
|
range.start.to_offset(self)..range.end.to_offset(self),
|
||||||
|
reversed,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1575,7 +1575,7 @@ impl BufferSnapshot {
|
||||||
let mut diagnostic_endpoints = Vec::new();
|
let mut diagnostic_endpoints = Vec::new();
|
||||||
if language_aware {
|
if language_aware {
|
||||||
tree = self.tree.as_ref();
|
tree = self.tree.as_ref();
|
||||||
for entry in self.diagnostics_in_range::<_, usize>(range.clone()) {
|
for entry in self.diagnostics_in_range::<_, usize>(range.clone(), false) {
|
||||||
diagnostic_endpoints.push(DiagnosticEndpoint {
|
diagnostic_endpoints.push(DiagnosticEndpoint {
|
||||||
offset: entry.range.start,
|
offset: entry.range.start,
|
||||||
is_start: true,
|
is_start: true,
|
||||||
|
@ -1838,12 +1838,14 @@ impl BufferSnapshot {
|
||||||
pub fn diagnostics_in_range<'a, T, O>(
|
pub fn diagnostics_in_range<'a, T, O>(
|
||||||
&'a self,
|
&'a self,
|
||||||
search_range: Range<T>,
|
search_range: Range<T>,
|
||||||
|
reversed: bool,
|
||||||
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
|
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
|
||||||
where
|
where
|
||||||
T: 'a + Clone + ToOffset,
|
T: 'a + Clone + ToOffset,
|
||||||
O: 'a + FromAnchor,
|
O: 'a + FromAnchor,
|
||||||
{
|
{
|
||||||
self.diagnostics.range(search_range.clone(), self, true)
|
self.diagnostics
|
||||||
|
.range(search_range.clone(), self, true, reversed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diagnostic_groups(&self) -> Vec<DiagnosticGroup<Anchor>> {
|
pub fn diagnostic_groups(&self) -> Vec<DiagnosticGroup<Anchor>> {
|
||||||
|
|
|
@ -71,6 +71,7 @@ impl DiagnosticSet {
|
||||||
range: Range<T>,
|
range: Range<T>,
|
||||||
buffer: &'a text::BufferSnapshot,
|
buffer: &'a text::BufferSnapshot,
|
||||||
inclusive: bool,
|
inclusive: bool,
|
||||||
|
reversed: bool,
|
||||||
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
|
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
|
||||||
where
|
where
|
||||||
T: 'a + ToOffset,
|
T: 'a + ToOffset,
|
||||||
|
@ -90,11 +91,19 @@ impl DiagnosticSet {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if reversed {
|
||||||
|
cursor.prev(buffer);
|
||||||
|
} else {
|
||||||
cursor.next(buffer);
|
cursor.next(buffer);
|
||||||
|
}
|
||||||
iter::from_fn({
|
iter::from_fn({
|
||||||
move || {
|
move || {
|
||||||
if let Some(diagnostic) = cursor.item() {
|
if let Some(diagnostic) = cursor.item() {
|
||||||
|
if reversed {
|
||||||
|
cursor.prev(buffer);
|
||||||
|
} else {
|
||||||
cursor.next(buffer);
|
cursor.next(buffer);
|
||||||
|
}
|
||||||
Some(diagnostic.resolve(buffer))
|
Some(diagnostic.resolve(buffer))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -768,10 +768,10 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer
|
buffer
|
||||||
.diagnostics_in_range::<_, usize>(0..buffer.len())
|
.diagnostics_in_range::<_, usize>(0..buffer.len(), false)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
first_buffer
|
first_buffer
|
||||||
.diagnostics_in_range::<_, usize>(0..first_buffer.len())
|
.diagnostics_in_range::<_, usize>(0..first_buffer.len(), false)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
"Replica {} diagnostics != Replica 0 diagnostics",
|
"Replica {} diagnostics != Replica 0 diagnostics",
|
||||||
buffer.replica_id()
|
buffer.replica_id()
|
||||||
|
|
|
@ -4869,7 +4869,7 @@ mod tests {
|
||||||
buffer.read_with(cx, |buffer, _| {
|
buffer.read_with(cx, |buffer, _| {
|
||||||
let snapshot = buffer.snapshot();
|
let snapshot = buffer.snapshot();
|
||||||
let diagnostics = snapshot
|
let diagnostics = snapshot
|
||||||
.diagnostics_in_range::<_, Point>(0..buffer.len())
|
.diagnostics_in_range::<_, Point>(0..buffer.len(), false)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
diagnostics,
|
diagnostics,
|
||||||
|
@ -4985,7 +4985,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer
|
buffer
|
||||||
.snapshot()
|
.snapshot()
|
||||||
.diagnostics_in_range::<_, Point>(Point::new(3, 0)..Point::new(5, 0))
|
.diagnostics_in_range::<_, Point>(Point::new(3, 0)..Point::new(5, 0), false)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
DiagnosticEntry {
|
DiagnosticEntry {
|
||||||
|
@ -5063,7 +5063,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer
|
buffer
|
||||||
.snapshot()
|
.snapshot()
|
||||||
.diagnostics_in_range::<_, Point>(Point::new(2, 0)..Point::new(3, 0))
|
.diagnostics_in_range::<_, Point>(Point::new(2, 0)..Point::new(3, 0), false)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
DiagnosticEntry {
|
DiagnosticEntry {
|
||||||
|
@ -5150,7 +5150,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer
|
buffer
|
||||||
.snapshot()
|
.snapshot()
|
||||||
.diagnostics_in_range::<_, Point>(0..buffer.len())
|
.diagnostics_in_range::<_, Point>(0..buffer.len(), false)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
DiagnosticEntry {
|
DiagnosticEntry {
|
||||||
|
@ -6428,7 +6428,7 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer
|
buffer
|
||||||
.diagnostics_in_range::<_, Point>(0..buffer.len())
|
.diagnostics_in_range::<_, Point>(0..buffer.len(), false)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
DiagnosticEntry {
|
DiagnosticEntry {
|
||||||
|
|
|
@ -2061,7 +2061,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer
|
buffer
|
||||||
.snapshot()
|
.snapshot()
|
||||||
.diagnostics_in_range::<_, Point>(0..buffer.len())
|
.diagnostics_in_range::<_, Point>(0..buffer.len(), false)
|
||||||
.map(|entry| entry)
|
.map(|entry| entry)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
&[
|
&[
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue