bump protocol version and fix panic from storing display points instead of anchors
This commit is contained in:
parent
a0577f5f46
commit
f73af85218
3 changed files with 49 additions and 35 deletions
|
@ -7,7 +7,7 @@ use settings::Settings;
|
||||||
use util::TryFutureExt;
|
use util::TryFutureExt;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
use crate::{Anchor, DisplayPoint, Editor, GoToDefinition};
|
use crate::{Anchor, DisplayPoint, Editor, EditorSnapshot, GoToDefinition, Select, SelectPhase};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct UpdateGoToDefinitionLink {
|
pub struct UpdateGoToDefinitionLink {
|
||||||
|
@ -38,8 +38,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LinkGoToDefinitionState {
|
pub struct LinkGoToDefinitionState {
|
||||||
pub last_mouse_point: Option<DisplayPoint>,
|
pub last_mouse_location: Option<Anchor>,
|
||||||
pub triggered_from: Option<Anchor>,
|
|
||||||
pub symbol_range: Option<Range<Anchor>>,
|
pub symbol_range: Option<Range<Anchor>>,
|
||||||
pub definitions: Vec<LocationLink>,
|
pub definitions: Vec<LocationLink>,
|
||||||
pub task: Option<Task<Option<()>>>,
|
pub task: Option<Task<Option<()>>>,
|
||||||
|
@ -50,10 +49,28 @@ pub fn update_go_to_definition_link(
|
||||||
&UpdateGoToDefinitionLink { point, cmd_held }: &UpdateGoToDefinitionLink,
|
&UpdateGoToDefinitionLink { point, cmd_held }: &UpdateGoToDefinitionLink,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
editor.link_go_to_definition_state.last_mouse_point = point;
|
// Store new mouse point as an anchor
|
||||||
|
let snapshot = editor.snapshot(cx);
|
||||||
|
let point = point.map(|point| {
|
||||||
|
snapshot
|
||||||
|
.buffer_snapshot
|
||||||
|
.anchor_before(point.to_offset(&snapshot.display_snapshot, Bias::Left))
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the new point is the same as the previously stored one, return early
|
||||||
|
if let (Some(a), Some(b)) = (
|
||||||
|
&point,
|
||||||
|
&editor.link_go_to_definition_state.last_mouse_location,
|
||||||
|
) {
|
||||||
|
if a.cmp(&b, &snapshot.buffer_snapshot).is_eq() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.link_go_to_definition_state.last_mouse_location = point.clone();
|
||||||
if cmd_held {
|
if cmd_held {
|
||||||
if let Some(point) = point {
|
if let Some(point) = point {
|
||||||
show_link_definition(editor, point, cx);
|
show_link_definition(editor, point, snapshot, cx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,9 +83,14 @@ pub fn cmd_changed(
|
||||||
&CmdChanged { cmd_down }: &CmdChanged,
|
&CmdChanged { cmd_down }: &CmdChanged,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
if let Some(point) = editor.link_go_to_definition_state.last_mouse_point {
|
if let Some(point) = editor
|
||||||
|
.link_go_to_definition_state
|
||||||
|
.last_mouse_location
|
||||||
|
.clone()
|
||||||
|
{
|
||||||
if cmd_down {
|
if cmd_down {
|
||||||
show_link_definition(editor, point, cx);
|
let snapshot = editor.snapshot(cx);
|
||||||
|
show_link_definition(editor, point.clone(), snapshot, cx);
|
||||||
} else {
|
} else {
|
||||||
hide_link_definition(editor, cx)
|
hide_link_definition(editor, cx)
|
||||||
}
|
}
|
||||||
|
@ -77,20 +99,18 @@ pub fn cmd_changed(
|
||||||
|
|
||||||
pub fn show_link_definition(
|
pub fn show_link_definition(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
point: DisplayPoint,
|
trigger_point: Anchor,
|
||||||
|
snapshot: EditorSnapshot,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
if editor.pending_rename.is_some() {
|
if editor.pending_rename.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let snapshot = editor.snapshot(cx);
|
|
||||||
let multibuffer_offset = point.to_offset(&snapshot.display_snapshot, Bias::Left);
|
|
||||||
|
|
||||||
let (buffer, buffer_position) = if let Some(output) = editor
|
let (buffer, buffer_position) = if let Some(output) = editor
|
||||||
.buffer
|
.buffer
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.text_anchor_for_position(multibuffer_offset, cx)
|
.text_anchor_for_position(trigger_point.clone(), cx)
|
||||||
{
|
{
|
||||||
output
|
output
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,7 +120,7 @@ pub fn show_link_definition(
|
||||||
let excerpt_id = if let Some((excerpt_id, _, _)) = editor
|
let excerpt_id = if let Some((excerpt_id, _, _)) = editor
|
||||||
.buffer()
|
.buffer()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.excerpt_containing(multibuffer_offset, cx)
|
.excerpt_containing(trigger_point.clone(), cx)
|
||||||
{
|
{
|
||||||
excerpt_id
|
excerpt_id
|
||||||
} else {
|
} else {
|
||||||
|
@ -113,36 +133,21 @@ pub fn show_link_definition(
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get input anchor
|
|
||||||
let anchor = snapshot
|
|
||||||
.buffer_snapshot
|
|
||||||
.anchor_at(multibuffer_offset, Bias::Left);
|
|
||||||
|
|
||||||
// Don't request again if the location is within the symbol region of a previous request
|
// Don't request again if the location is within the symbol region of a previous request
|
||||||
if let Some(symbol_range) = &editor.link_go_to_definition_state.symbol_range {
|
if let Some(symbol_range) = &editor.link_go_to_definition_state.symbol_range {
|
||||||
if symbol_range
|
if symbol_range
|
||||||
.start
|
.start
|
||||||
.cmp(&anchor, &snapshot.buffer_snapshot)
|
.cmp(&trigger_point, &snapshot.buffer_snapshot)
|
||||||
.is_le()
|
.is_le()
|
||||||
&& symbol_range
|
&& symbol_range
|
||||||
.end
|
.end
|
||||||
.cmp(&anchor, &snapshot.buffer_snapshot)
|
.cmp(&trigger_point, &snapshot.buffer_snapshot)
|
||||||
.is_ge()
|
.is_ge()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't request from the exact same location again
|
|
||||||
if let Some(triggered_from) = &editor.link_go_to_definition_state.triggered_from {
|
|
||||||
if triggered_from
|
|
||||||
.cmp(&anchor, &snapshot.buffer_snapshot)
|
|
||||||
.is_eq()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let task = cx.spawn_weak(|this, mut cx| {
|
let task = cx.spawn_weak(|this, mut cx| {
|
||||||
async move {
|
async move {
|
||||||
// query the LSP for definition info
|
// query the LSP for definition info
|
||||||
|
@ -174,7 +179,6 @@ pub fn show_link_definition(
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
// Clear any existing highlights
|
// Clear any existing highlights
|
||||||
this.clear_text_highlights::<LinkGoToDefinitionState>(cx);
|
this.clear_text_highlights::<LinkGoToDefinitionState>(cx);
|
||||||
this.link_go_to_definition_state.triggered_from = Some(anchor.clone());
|
|
||||||
this.link_go_to_definition_state.symbol_range = result
|
this.link_go_to_definition_state.symbol_range = result
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|(symbol_range, _)| symbol_range.clone());
|
.and_then(|(symbol_range, _)| symbol_range.clone());
|
||||||
|
@ -208,7 +212,7 @@ pub fn show_link_definition(
|
||||||
// If no symbol range returned from language server, use the surrounding word.
|
// If no symbol range returned from language server, use the surrounding word.
|
||||||
let highlight_range = symbol_range.unwrap_or_else(|| {
|
let highlight_range = symbol_range.unwrap_or_else(|| {
|
||||||
let snapshot = &snapshot.buffer_snapshot;
|
let snapshot = &snapshot.buffer_snapshot;
|
||||||
let (offset_range, _) = snapshot.surrounding_word(anchor);
|
let (offset_range, _) = snapshot.surrounding_word(trigger_point);
|
||||||
|
|
||||||
snapshot.anchor_before(offset_range.start)
|
snapshot.anchor_before(offset_range.start)
|
||||||
..snapshot.anchor_after(offset_range.end)
|
..snapshot.anchor_after(offset_range.end)
|
||||||
|
@ -245,7 +249,6 @@ pub fn hide_link_definition(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.link_go_to_definition_state.triggered_from = None;
|
|
||||||
editor.link_go_to_definition_state.task = None;
|
editor.link_go_to_definition_state.task = None;
|
||||||
|
|
||||||
editor.clear_text_highlights::<LinkGoToDefinitionState>(cx);
|
editor.clear_text_highlights::<LinkGoToDefinitionState>(cx);
|
||||||
|
@ -276,7 +279,14 @@ pub fn go_to_fetched_definition(
|
||||||
Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
|
Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
|
||||||
} else {
|
} else {
|
||||||
editor_handle.update(cx, |editor, cx| {
|
editor_handle.update(cx, |editor, cx| {
|
||||||
editor.change_selections(None, cx, |s| s.select_display_ranges(vec![*point..*point]));
|
editor.select(
|
||||||
|
&Select(SelectPhase::Begin {
|
||||||
|
position: point.clone(),
|
||||||
|
add: false,
|
||||||
|
click_count: 1,
|
||||||
|
}),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Editor::go_to_definition(workspace, &GoToDefinition, cx);
|
Editor::go_to_definition(workspace, &GoToDefinition, cx);
|
||||||
|
@ -375,6 +385,7 @@ mod tests {
|
||||||
test();"});
|
test();"});
|
||||||
|
|
||||||
// Response without source range still highlights word
|
// Response without source range still highlights word
|
||||||
|
cx.update_editor(|editor, _| editor.link_go_to_definition_state.last_mouse_location = None);
|
||||||
let mut requests =
|
let mut requests =
|
||||||
cx.lsp
|
cx.lsp
|
||||||
.handle_request::<lsp::request::GotoDefinition, _, _>(move |_, _| async move {
|
.handle_request::<lsp::request::GotoDefinition, _, _>(move |_, _| async move {
|
||||||
|
@ -400,6 +411,8 @@ mod tests {
|
||||||
});
|
});
|
||||||
requests.next().await;
|
requests.next().await;
|
||||||
cx.foreground().run_until_parked();
|
cx.foreground().run_until_parked();
|
||||||
|
|
||||||
|
println!("tag");
|
||||||
cx.assert_editor_text_highlights::<LinkGoToDefinitionState>(indoc! {"
|
cx.assert_editor_text_highlights::<LinkGoToDefinitionState>(indoc! {"
|
||||||
fn test()
|
fn test()
|
||||||
[do_work]();
|
[do_work]();
|
||||||
|
|
|
@ -536,6 +536,7 @@ impl<'a> MutableSelectionsCollection<'a> {
|
||||||
self.select_anchors(selections)
|
self.select_anchors(selections)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn select_display_ranges<T>(&mut self, ranges: T)
|
pub fn select_display_ranges<T>(&mut self, ranges: T)
|
||||||
where
|
where
|
||||||
T: IntoIterator<Item = Range<DisplayPoint>>,
|
T: IntoIterator<Item = Range<DisplayPoint>>,
|
||||||
|
|
|
@ -6,4 +6,4 @@ pub use conn::Connection;
|
||||||
pub use peer::*;
|
pub use peer::*;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub const PROTOCOL_VERSION: u32 = 25;
|
pub const PROTOCOL_VERSION: u32 = 26;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue