@@ -21,7 +21,7 @@ mod editor_tests;
#[cfg(any(test, feature = "test-support"))]
pub mod test;
use aho_corasick::AhoCorasick;
-use anyhow::Result;
+use anyhow::{Context as _, Result};
use blink_manager::BlinkManager;
use client::{ClickhouseEvent, Client, Collaborator, ParticipantIndex, TelemetrySettings};
use clock::ReplicaId;
@@ -36,9 +36,9 @@ pub use element::{
use futures::FutureExt;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
- AnyElement, AppContext, BackgroundExecutor, Context, Element, EventEmitter, FocusHandle, Hsla,
- Model, Pixels, Render, Subscription, Task, TextStyle, View, ViewContext, WeakView,
- WindowContext,
+ div, AnyElement, AppContext, BackgroundExecutor, Context, Div, Element, EventEmitter,
+ FocusHandle, Hsla, Model, Pixels, Render, Subscription, Task, TextStyle, View, ViewContext,
+ VisualContext, WeakView, WindowContext,
};
use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HoverState};
@@ -48,10 +48,11 @@ use itertools::Itertools;
pub use language::{char_kind, CharKind};
use language::{
language_settings::{self, all_language_settings, InlayHintSettings},
- AutoindentMode, BracketPair, Buffer, CodeAction, Completion, CursorShape, Diagnostic, Language,
- LanguageRegistry, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
+ point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, Completion, CursorShape,
+ Diagnostic, Language, LanguageRegistry, LanguageServerName, OffsetRangeExt, Point, Selection,
+ SelectionGoal, TransactionId,
};
-use link_go_to_definition::{InlayHighlight, LinkGoToDefinitionState};
+use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
use lsp::{Documentation, LanguageServerId};
pub use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
@@ -59,7 +60,7 @@ pub use multi_buffer::{
};
use ordered_float::OrderedFloat;
use parking_lot::RwLock;
-use project::{FormatTrigger, Project};
+use project::{FormatTrigger, Location, Project};
use rpc::proto::*;
use scroll::{
autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
@@ -69,6 +70,7 @@ use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use std::{
any::TypeId,
+ borrow::Cow,
cmp::{self, Reverse},
ops::{ControlFlow, Deref, DerefMut, Range},
path::Path,
@@ -80,7 +82,7 @@ use sum_tree::TreeMap;
use text::Rope;
use theme::ThemeColors;
use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
-use workspace::{ItemNavHistory, ViewId, Workspace};
+use workspace::{ItemNavHistory, SplitDirection, ViewId, Workspace};
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
const MAX_LINE_LEN: usize = 1024;
@@ -389,6 +391,10 @@ impl InlayId {
// todo!(revisit these actions)
pub struct ShowCompletions;
pub struct Rename;
+pub struct GoToDefinition;
+pub struct GoToTypeDefinition;
+pub struct GoToDefinitionSplit;
+pub struct GoToTypeDefinitionSplit;
enum DocumentHighlightRead {}
enum DocumentHighlightWrite {}
@@ -561,7 +567,7 @@ pub enum SelectPhase {
Update {
position: DisplayPoint,
goal_column: u32,
- scroll_position: gpui::Point<Pixels>,
+ scroll_position: gpui::Point<f32>,
},
End,
}
@@ -1836,13 +1842,13 @@ impl Editor {
Self::new(EditorMode::Full, buffer, project, cx)
}
- // pub fn for_multibuffer(
- // buffer: Model<MultiBuffer>,
- // project: Option<Model<Project>>,
- // cx: &mut ViewContext<Self>,
- // ) -> Self {
- // Self::new(EditorMode::Full, buffer, project, None, cx)
- // }
+ pub fn for_multibuffer(
+ buffer: Model<MultiBuffer>,
+ project: Option<Model<Project>>,
+ cx: &mut ViewContext<Self>,
+ ) -> Self {
+ Self::new(EditorMode::Full, buffer, project, cx)
+ }
pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
let mut clone = Self::new(
@@ -2048,9 +2054,9 @@ impl Editor {
// }
// }
- // pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
- // self.buffer.read(cx).replica_id()
- // }
+ pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
+ self.buffer.read(cx).replica_id()
+ }
// pub fn leader_peer_id(&self) -> Option<PeerId> {
// self.leader_peer_id
@@ -2060,13 +2066,13 @@ impl Editor {
&self.buffer
}
- // fn workspace(&self, cx: &AppContext) -> Option<ViewHandle<Workspace>> {
- // self.workspace.as_ref()?.0.upgrade(cx)
- // }
+ fn workspace(&self) -> Option<View<Workspace>> {
+ self.workspace.as_ref()?.0.upgrade()
+ }
- // pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
- // self.buffer().read(cx).title(cx)
- // }
+ pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
+ self.buffer().read(cx).title(cx)
+ }
pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
EditorSnapshot {
@@ -2140,12 +2146,12 @@ impl Editor {
// self.collapse_matches = collapse_matches;
// }
- // pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
- // if self.collapse_matches {
- // return range.start..range.start;
- // }
- // range.clone()
- // }
+ pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
+ if self.collapse_matches {
+ return range.start..range.start;
+ }
+ range.clone()
+ }
// pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
// if self.display_map.read(cx).clip_at_line_ends != clip {
@@ -2383,253 +2389,253 @@ impl Editor {
// });
// }
- // fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
- // self.hide_context_menu(cx);
-
- // match phase {
- // SelectPhase::Begin {
- // position,
- // add,
- // click_count,
- // } => self.begin_selection(position, add, click_count, cx),
- // SelectPhase::BeginColumnar {
- // position,
- // goal_column,
- // } => self.begin_columnar_selection(position, goal_column, cx),
- // SelectPhase::Extend {
- // position,
- // click_count,
- // } => self.extend_selection(position, click_count, cx),
- // SelectPhase::Update {
- // position,
- // goal_column,
- // scroll_position,
- // } => self.update_selection(position, goal_column, scroll_position, cx),
- // SelectPhase::End => self.end_selection(cx),
- // }
- // }
-
- // fn extend_selection(
- // &mut self,
- // position: DisplayPoint,
- // click_count: usize,
- // cx: &mut ViewContext<Self>,
- // ) {
- // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- // let tail = self.selections.newest::<usize>(cx).tail();
- // self.begin_selection(position, false, click_count, cx);
-
- // let position = position.to_offset(&display_map, Bias::Left);
- // let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
+ fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
+ self.hide_context_menu(cx);
+
+ match phase {
+ SelectPhase::Begin {
+ position,
+ add,
+ click_count,
+ } => self.begin_selection(position, add, click_count, cx),
+ SelectPhase::BeginColumnar {
+ position,
+ goal_column,
+ } => self.begin_columnar_selection(position, goal_column, cx),
+ SelectPhase::Extend {
+ position,
+ click_count,
+ } => self.extend_selection(position, click_count, cx),
+ SelectPhase::Update {
+ position,
+ goal_column,
+ scroll_position,
+ } => self.update_selection(position, goal_column, scroll_position, cx),
+ SelectPhase::End => self.end_selection(cx),
+ }
+ }
- // let mut pending_selection = self
- // .selections
- // .pending_anchor()
- // .expect("extend_selection not called with pending selection");
- // if position >= tail {
- // pending_selection.start = tail_anchor;
- // } else {
- // pending_selection.end = tail_anchor;
- // pending_selection.reversed = true;
- // }
+ fn extend_selection(
+ &mut self,
+ position: DisplayPoint,
+ click_count: usize,
+ cx: &mut ViewContext<Self>,
+ ) {
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let tail = self.selections.newest::<usize>(cx).tail();
+ self.begin_selection(position, false, click_count, cx);
+
+ let position = position.to_offset(&display_map, Bias::Left);
+ let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
+
+ let mut pending_selection = self
+ .selections
+ .pending_anchor()
+ .expect("extend_selection not called with pending selection");
+ if position >= tail {
+ pending_selection.start = tail_anchor;
+ } else {
+ pending_selection.end = tail_anchor;
+ pending_selection.reversed = true;
+ }
- // let mut pending_mode = self.selections.pending_mode().unwrap();
- // match &mut pending_mode {
- // SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
- // _ => {}
- // }
+ let mut pending_mode = self.selections.pending_mode().unwrap();
+ match &mut pending_mode {
+ SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
+ _ => {}
+ }
- // self.change_selections(Some(Autoscroll::fit()), cx, |s| {
- // s.set_pending(pending_selection, pending_mode)
- // });
- // }
+ self.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ s.set_pending(pending_selection, pending_mode)
+ });
+ }
- // fn begin_selection(
- // &mut self,
- // position: DisplayPoint,
- // add: bool,
- // click_count: usize,
- // cx: &mut ViewContext<Self>,
- // ) {
- // if !self.focused {
- // cx.focus_self();
- // }
+ fn begin_selection(
+ &mut self,
+ position: DisplayPoint,
+ add: bool,
+ click_count: usize,
+ cx: &mut ViewContext<Self>,
+ ) {
+ if !self.focused {
+ cx.focus(&self.focus_handle);
+ }
- // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- // let buffer = &display_map.buffer_snapshot;
- // let newest_selection = self.selections.newest_anchor().clone();
- // let position = display_map.clip_point(position, Bias::Left);
-
- // let start;
- // let end;
- // let mode;
- // let auto_scroll;
- // match click_count {
- // 1 => {
- // start = buffer.anchor_before(position.to_point(&display_map));
- // end = start.clone();
- // mode = SelectMode::Character;
- // auto_scroll = true;
- // }
- // 2 => {
- // let range = movement::surrounding_word(&display_map, position);
- // start = buffer.anchor_before(range.start.to_point(&display_map));
- // end = buffer.anchor_before(range.end.to_point(&display_map));
- // mode = SelectMode::Word(start.clone()..end.clone());
- // auto_scroll = true;
- // }
- // 3 => {
- // let position = display_map
- // .clip_point(position, Bias::Left)
- // .to_point(&display_map);
- // let line_start = display_map.prev_line_boundary(position).0;
- // let next_line_start = buffer.clip_point(
- // display_map.next_line_boundary(position).0 + Point::new(1, 0),
- // Bias::Left,
- // );
- // start = buffer.anchor_before(line_start);
- // end = buffer.anchor_before(next_line_start);
- // mode = SelectMode::Line(start.clone()..end.clone());
- // auto_scroll = true;
- // }
- // _ => {
- // start = buffer.anchor_before(0);
- // end = buffer.anchor_before(buffer.len());
- // mode = SelectMode::All;
- // auto_scroll = false;
- // }
- // }
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let buffer = &display_map.buffer_snapshot;
+ let newest_selection = self.selections.newest_anchor().clone();
+ let position = display_map.clip_point(position, Bias::Left);
+
+ let start;
+ let end;
+ let mode;
+ let auto_scroll;
+ match click_count {
+ 1 => {
+ start = buffer.anchor_before(position.to_point(&display_map));
+ end = start.clone();
+ mode = SelectMode::Character;
+ auto_scroll = true;
+ }
+ 2 => {
+ let range = movement::surrounding_word(&display_map, position);
+ start = buffer.anchor_before(range.start.to_point(&display_map));
+ end = buffer.anchor_before(range.end.to_point(&display_map));
+ mode = SelectMode::Word(start.clone()..end.clone());
+ auto_scroll = true;
+ }
+ 3 => {
+ let position = display_map
+ .clip_point(position, Bias::Left)
+ .to_point(&display_map);
+ let line_start = display_map.prev_line_boundary(position).0;
+ let next_line_start = buffer.clip_point(
+ display_map.next_line_boundary(position).0 + Point::new(1, 0),
+ Bias::Left,
+ );
+ start = buffer.anchor_before(line_start);
+ end = buffer.anchor_before(next_line_start);
+ mode = SelectMode::Line(start.clone()..end.clone());
+ auto_scroll = true;
+ }
+ _ => {
+ start = buffer.anchor_before(0);
+ end = buffer.anchor_before(buffer.len());
+ mode = SelectMode::All;
+ auto_scroll = false;
+ }
+ }
- // self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
- // if !add {
- // s.clear_disjoint();
- // } else if click_count > 1 {
- // s.delete(newest_selection.id)
- // }
+ self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
+ if !add {
+ s.clear_disjoint();
+ } else if click_count > 1 {
+ s.delete(newest_selection.id)
+ }
- // s.set_pending_anchor_range(start..end, mode);
- // });
- // }
+ s.set_pending_anchor_range(start..end, mode);
+ });
+ }
- // fn begin_columnar_selection(
- // &mut self,
- // position: DisplayPoint,
- // goal_column: u32,
- // cx: &mut ViewContext<Self>,
- // ) {
- // if !self.focused {
- // cx.focus_self();
- // }
+ fn begin_columnar_selection(
+ &mut self,
+ position: DisplayPoint,
+ goal_column: u32,
+ cx: &mut ViewContext<Self>,
+ ) {
+ if !self.focused {
+ cx.focus(&self.focus_handle);
+ }
- // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- // let tail = self.selections.newest::<Point>(cx).tail();
- // self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let tail = self.selections.newest::<Point>(cx).tail();
+ self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
- // self.select_columns(
- // tail.to_display_point(&display_map),
- // position,
- // goal_column,
- // &display_map,
- // cx,
- // );
- // }
+ self.select_columns(
+ tail.to_display_point(&display_map),
+ position,
+ goal_column,
+ &display_map,
+ cx,
+ );
+ }
- // fn update_selection(
- // &mut self,
- // position: DisplayPoint,
- // goal_column: u32,
- // scroll_position: Vector2F,
- // cx: &mut ViewContext<Self>,
- // ) {
- // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ fn update_selection(
+ &mut self,
+ position: DisplayPoint,
+ goal_column: u32,
+ scroll_position: gpui::Point<f32>,
+ cx: &mut ViewContext<Self>,
+ ) {
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- // if let Some(tail) = self.columnar_selection_tail.as_ref() {
- // let tail = tail.to_display_point(&display_map);
- // self.select_columns(tail, position, goal_column, &display_map, cx);
- // } else if let Some(mut pending) = self.selections.pending_anchor() {
- // let buffer = self.buffer.read(cx).snapshot(cx);
- // let head;
- // let tail;
- // let mode = self.selections.pending_mode().unwrap();
- // match &mode {
- // SelectMode::Character => {
- // head = position.to_point(&display_map);
- // tail = pending.tail().to_point(&buffer);
- // }
- // SelectMode::Word(original_range) => {
- // let original_display_range = original_range.start.to_display_point(&display_map)
- // ..original_range.end.to_display_point(&display_map);
- // let original_buffer_range = original_display_range.start.to_point(&display_map)
- // ..original_display_range.end.to_point(&display_map);
- // if movement::is_inside_word(&display_map, position)
- // || original_display_range.contains(&position)
- // {
- // let word_range = movement::surrounding_word(&display_map, position);
- // if word_range.start < original_display_range.start {
- // head = word_range.start.to_point(&display_map);
- // } else {
- // head = word_range.end.to_point(&display_map);
- // }
- // } else {
- // head = position.to_point(&display_map);
- // }
+ if let Some(tail) = self.columnar_selection_tail.as_ref() {
+ let tail = tail.to_display_point(&display_map);
+ self.select_columns(tail, position, goal_column, &display_map, cx);
+ } else if let Some(mut pending) = self.selections.pending_anchor() {
+ let buffer = self.buffer.read(cx).snapshot(cx);
+ let head;
+ let tail;
+ let mode = self.selections.pending_mode().unwrap();
+ match &mode {
+ SelectMode::Character => {
+ head = position.to_point(&display_map);
+ tail = pending.tail().to_point(&buffer);
+ }
+ SelectMode::Word(original_range) => {
+ let original_display_range = original_range.start.to_display_point(&display_map)
+ ..original_range.end.to_display_point(&display_map);
+ let original_buffer_range = original_display_range.start.to_point(&display_map)
+ ..original_display_range.end.to_point(&display_map);
+ if movement::is_inside_word(&display_map, position)
+ || original_display_range.contains(&position)
+ {
+ let word_range = movement::surrounding_word(&display_map, position);
+ if word_range.start < original_display_range.start {
+ head = word_range.start.to_point(&display_map);
+ } else {
+ head = word_range.end.to_point(&display_map);
+ }
+ } else {
+ head = position.to_point(&display_map);
+ }
- // if head <= original_buffer_range.start {
- // tail = original_buffer_range.end;
- // } else {
- // tail = original_buffer_range.start;
- // }
- // }
- // SelectMode::Line(original_range) => {
- // let original_range = original_range.to_point(&display_map.buffer_snapshot);
-
- // let position = display_map
- // .clip_point(position, Bias::Left)
- // .to_point(&display_map);
- // let line_start = display_map.prev_line_boundary(position).0;
- // let next_line_start = buffer.clip_point(
- // display_map.next_line_boundary(position).0 + Point::new(1, 0),
- // Bias::Left,
- // );
+ if head <= original_buffer_range.start {
+ tail = original_buffer_range.end;
+ } else {
+ tail = original_buffer_range.start;
+ }
+ }
+ SelectMode::Line(original_range) => {
+ let original_range = original_range.to_point(&display_map.buffer_snapshot);
+
+ let position = display_map
+ .clip_point(position, Bias::Left)
+ .to_point(&display_map);
+ let line_start = display_map.prev_line_boundary(position).0;
+ let next_line_start = buffer.clip_point(
+ display_map.next_line_boundary(position).0 + Point::new(1, 0),
+ Bias::Left,
+ );
- // if line_start < original_range.start {
- // head = line_start
- // } else {
- // head = next_line_start
- // }
+ if line_start < original_range.start {
+ head = line_start
+ } else {
+ head = next_line_start
+ }
- // if head <= original_range.start {
- // tail = original_range.end;
- // } else {
- // tail = original_range.start;
- // }
- // }
- // SelectMode::All => {
- // return;
- // }
- // };
+ if head <= original_range.start {
+ tail = original_range.end;
+ } else {
+ tail = original_range.start;
+ }
+ }
+ SelectMode::All => {
+ return;
+ }
+ };
- // if head < tail {
- // pending.start = buffer.anchor_before(head);
- // pending.end = buffer.anchor_before(tail);
- // pending.reversed = true;
- // } else {
- // pending.start = buffer.anchor_before(tail);
- // pending.end = buffer.anchor_before(head);
- // pending.reversed = false;
- // }
+ if head < tail {
+ pending.start = buffer.anchor_before(head);
+ pending.end = buffer.anchor_before(tail);
+ pending.reversed = true;
+ } else {
+ pending.start = buffer.anchor_before(tail);
+ pending.end = buffer.anchor_before(head);
+ pending.reversed = false;
+ }
- // self.change_selections(None, cx, |s| {
- // s.set_pending(pending, mode);
- // });
- // } else {
- // error!("update_selection dispatched with no pending selection");
- // return;
- // }
+ self.change_selections(None, cx, |s| {
+ s.set_pending(pending, mode);
+ });
+ } else {
+ log::error!("update_selection dispatched with no pending selection");
+ return;
+ }
- // self.set_scroll_position(scroll_position, cx);
- // cx.notify();
- // }
+ self.set_scroll_position(scroll_position, cx);
+ cx.notify();
+ }
fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
self.columnar_selection_tail.take();
@@ -7347,239 +7353,233 @@ impl Editor {
// }
// }
- // pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
- // self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
- // }
+ pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
+ self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
+ }
- // pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
- // self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
- // }
+ pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
+ self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
+ }
- // pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
- // self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
- // }
+ pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
+ self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
+ }
- // pub fn go_to_type_definition_split(
- // &mut self,
- // _: &GoToTypeDefinitionSplit,
- // cx: &mut ViewContext<Self>,
- // ) {
- // self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
- // }
+ pub fn go_to_type_definition_split(
+ &mut self,
+ _: &GoToTypeDefinitionSplit,
+ cx: &mut ViewContext<Self>,
+ ) {
+ self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
+ }
- // fn go_to_definition_of_kind(
- // &mut self,
- // kind: GotoDefinitionKind,
- // split: bool,
- // cx: &mut ViewContext<Self>,
- // ) {
- // let Some(workspace) = self.workspace(cx) else {
- // return;
- // };
- // let buffer = self.buffer.read(cx);
- // let head = self.selections.newest::<usize>(cx).head();
- // let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
- // text_anchor
- // } else {
- // return;
- // };
+ fn go_to_definition_of_kind(
+ &mut self,
+ kind: GotoDefinitionKind,
+ split: bool,
+ cx: &mut ViewContext<Self>,
+ ) {
+ let Some(workspace) = self.workspace() else {
+ return;
+ };
+ let buffer = self.buffer.read(cx);
+ let head = self.selections.newest::<usize>(cx).head();
+ let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
+ text_anchor
+ } else {
+ return;
+ };
- // let project = workspace.read(cx).project().clone();
- // let definitions = project.update(cx, |project, cx| match kind {
- // GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
- // GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
- // });
+ let project = workspace.read(cx).project().clone();
+ let definitions = project.update(cx, |project, cx| match kind {
+ GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
+ GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
+ });
- // cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
- // let definitions = definitions.await?;
- // editor.update(&mut cx, |editor, cx| {
- // editor.navigate_to_definitions(
- // definitions
- // .into_iter()
- // .map(GoToDefinitionLink::Text)
- // .collect(),
- // split,
- // cx,
- // );
- // })?;
- // Ok::<(), anyhow::Error>(())
- // })
- // .detach_and_log_err(cx);
- // }
+ cx.spawn(|editor, mut cx| async move {
+ let definitions = definitions.await?;
+ editor.update(&mut cx, |editor, cx| {
+ editor.navigate_to_definitions(
+ definitions
+ .into_iter()
+ .map(GoToDefinitionLink::Text)
+ .collect(),
+ split,
+ cx,
+ );
+ })?;
+ Ok::<(), anyhow::Error>(())
+ })
+ .detach_and_log_err(cx);
+ }
- // pub fn navigate_to_definitions(
- // &mut self,
- // mut definitions: Vec<GoToDefinitionLink>,
- // split: bool,
- // cx: &mut ViewContext<Editor>,
- // ) {
- // let Some(workspace) = self.workspace(cx) else {
- // return;
- // };
- // let pane = workspace.read(cx).active_pane().clone();
- // // If there is one definition, just open it directly
- // if definitions.len() == 1 {
- // let definition = definitions.pop().unwrap();
- // let target_task = match definition {
- // GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
- // GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
- // self.compute_target_location(lsp_location, server_id, cx)
- // }
- // };
- // cx.spawn(|editor, mut cx| async move {
- // let target = target_task.await.context("target resolution task")?;
- // if let Some(target) = target {
- // editor.update(&mut cx, |editor, cx| {
- // let range = target.range.to_offset(target.buffer.read(cx));
- // let range = editor.range_for_match(&range);
- // if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
- // editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
- // s.select_ranges([range]);
- // });
- // } else {
- // cx.window_context().defer(move |cx| {
- // let target_editor: ViewHandle<Self> =
- // workspace.update(cx, |workspace, cx| {
- // if split {
- // workspace.split_project_item(target.buffer.clone(), cx)
- // } else {
- // workspace.open_project_item(target.buffer.clone(), cx)
- // }
- // });
- // target_editor.update(cx, |target_editor, cx| {
- // // When selecting a definition in a different buffer, disable the nav history
- // // to avoid creating a history entry at the previous cursor location.
- // pane.update(cx, |pane, _| pane.disable_history());
- // target_editor.change_selections(
- // Some(Autoscroll::fit()),
- // cx,
- // |s| {
- // s.select_ranges([range]);
- // },
- // );
- // pane.update(cx, |pane, _| pane.enable_history());
- // });
- // });
- // }
- // })
- // } else {
- // Ok(())
- // }
- // })
- // .detach_and_log_err(cx);
- // } else if !definitions.is_empty() {
- // let replica_id = self.replica_id(cx);
- // cx.spawn(|editor, mut cx| async move {
- // let (title, location_tasks) = editor
- // .update(&mut cx, |editor, cx| {
- // let title = definitions
- // .iter()
- // .find_map(|definition| match definition {
- // GoToDefinitionLink::Text(link) => {
- // link.origin.as_ref().map(|origin| {
- // let buffer = origin.buffer.read(cx);
- // format!(
- // "Definitions for {}",
- // buffer
- // .text_for_range(origin.range.clone())
- // .collect::<String>()
- // )
- // })
- // }
- // GoToDefinitionLink::InlayHint(_, _) => None,
- // })
- // .unwrap_or("Definitions".to_string());
- // let location_tasks = definitions
- // .into_iter()
- // .map(|definition| match definition {
- // GoToDefinitionLink::Text(link) => {
- // Task::Ready(Some(Ok(Some(link.target))))
- // }
- // GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
- // editor.compute_target_location(lsp_location, server_id, cx)
- // }
- // })
- // .collect::<Vec<_>>();
- // (title, location_tasks)
- // })
- // .context("location tasks preparation")?;
-
- // let locations = futures::future::join_all(location_tasks)
- // .await
- // .into_iter()
- // .filter_map(|location| location.transpose())
- // .collect::<Result<_>>()
- // .context("location tasks")?;
- // workspace.update(&mut cx, |workspace, cx| {
- // Self::open_locations_in_multibuffer(
- // workspace, locations, replica_id, title, split, cx,
- // )
- // });
+ pub fn navigate_to_definitions(
+ &mut self,
+ mut definitions: Vec<GoToDefinitionLink>,
+ split: bool,
+ cx: &mut ViewContext<Editor>,
+ ) {
+ let Some(workspace) = self.workspace() else {
+ return;
+ };
+ let pane = workspace.read(cx).active_pane().clone();
+ // If there is one definition, just open it directly
+ if definitions.len() == 1 {
+ let definition = definitions.pop().unwrap();
+ let target_task = match definition {
+ GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
+ GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
+ self.compute_target_location(lsp_location, server_id, cx)
+ }
+ };
+ cx.spawn(|editor, mut cx| async move {
+ let target = target_task.await.context("target resolution task")?;
+ if let Some(target) = target {
+ editor.update(&mut cx, |editor, cx| {
+ let range = target.range.to_offset(target.buffer.read(cx));
+ let range = editor.range_for_match(&range);
+ if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
+ editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ s.select_ranges([range]);
+ });
+ } else {
+ cx.window_context().defer(move |cx| {
+ let target_editor: View<Self> =
+ workspace.update(cx, |workspace, cx| {
+ if split {
+ workspace.split_project_item(target.buffer.clone(), cx)
+ } else {
+ workspace.open_project_item(target.buffer.clone(), cx)
+ }
+ });
+ target_editor.update(cx, |target_editor, cx| {
+ // When selecting a definition in a different buffer, disable the nav history
+ // to avoid creating a history entry at the previous cursor location.
+ pane.update(cx, |pane, _| pane.disable_history());
+ target_editor.change_selections(
+ Some(Autoscroll::fit()),
+ cx,
+ |s| {
+ s.select_ranges([range]);
+ },
+ );
+ pane.update(cx, |pane, _| pane.enable_history());
+ });
+ });
+ }
+ })
+ } else {
+ Ok(())
+ }
+ })
+ .detach_and_log_err(cx);
+ } else if !definitions.is_empty() {
+ let replica_id = self.replica_id(cx);
+ cx.spawn(|editor, mut cx| async move {
+ let (title, location_tasks) = editor
+ .update(&mut cx, |editor, cx| {
+ let title = definitions
+ .iter()
+ .find_map(|definition| match definition {
+ GoToDefinitionLink::Text(link) => {
+ link.origin.as_ref().map(|origin| {
+ let buffer = origin.buffer.read(cx);
+ format!(
+ "Definitions for {}",
+ buffer
+ .text_for_range(origin.range.clone())
+ .collect::<String>()
+ )
+ })
+ }
+ GoToDefinitionLink::InlayHint(_, _) => None,
+ })
+ .unwrap_or("Definitions".to_string());
+ let location_tasks = definitions
+ .into_iter()
+ .map(|definition| match definition {
+ GoToDefinitionLink::Text(link) => {
+ Task::Ready(Some(Ok(Some(link.target))))
+ }
+ GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
+ editor.compute_target_location(lsp_location, server_id, cx)
+ }
+ })
+ .collect::<Vec<_>>();
+ (title, location_tasks)
+ })
+ .context("location tasks preparation")?;
+
+ let locations = futures::future::join_all(location_tasks)
+ .await
+ .into_iter()
+ .filter_map(|location| location.transpose())
+ .collect::<Result<_>>()
+ .context("location tasks")?;
+ workspace.update(&mut cx, |workspace, cx| {
+ Self::open_locations_in_multibuffer(
+ workspace, locations, replica_id, title, split, cx,
+ )
+ });
- // anyhow::Ok(())
- // })
- // .detach_and_log_err(cx);
- // }
- // }
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
+ }
+ }
- // fn compute_target_location(
- // &self,
- // lsp_location: lsp::Location,
- // server_id: LanguageServerId,
- // cx: &mut ViewContext<Editor>,
- // ) -> Task<anyhow::Result<Option<Location>>> {
- // let Some(project) = self.project.clone() else {
- // return Task::Ready(Some(Ok(None)));
- // };
+ fn compute_target_location(
+ &self,
+ lsp_location: lsp::Location,
+ server_id: LanguageServerId,
+ cx: &mut ViewContext<Editor>,
+ ) -> Task<anyhow::Result<Option<Location>>> {
+ let Some(project) = self.project.clone() else {
+ return Task::Ready(Some(Ok(None)));
+ };
- // cx.spawn(move |editor, mut cx| async move {
- // let location_task = editor.update(&mut cx, |editor, cx| {
- // project.update(cx, |project, cx| {
- // let language_server_name =
- // editor.buffer.read(cx).as_singleton().and_then(|buffer| {
- // project
- // .language_server_for_buffer(buffer.read(cx), server_id, cx)
- // .map(|(_, lsp_adapter)| {
- // LanguageServerName(Arc::from(lsp_adapter.name()))
- // })
- // });
- // language_server_name.map(|language_server_name| {
- // project.open_local_buffer_via_lsp(
- // lsp_location.uri.clone(),
- // server_id,
- // language_server_name,
- // cx,
- // )
- // })
- // })
- // })?;
- // let location = match location_task {
- // Some(task) => Some({
- // let target_buffer_handle = task.await.context("open local buffer")?;
- // let range = {
- // target_buffer_handle.update(&mut cx, |target_buffer, _| {
- // let target_start = target_buffer.clip_point_utf16(
- // point_from_lsp(lsp_location.range.start),
- // Bias::Left,
- // );
- // let target_end = target_buffer.clip_point_utf16(
- // point_from_lsp(lsp_location.range.end),
- // Bias::Left,
- // );
- // target_buffer.anchor_after(target_start)
- // ..target_buffer.anchor_before(target_end)
- // })
- // };
- // Location {
- // buffer: target_buffer_handle,
- // range,
- // }
- // }),
- // None => None,
- // };
- // Ok(location)
- // })
- // }
+ cx.spawn(move |editor, mut cx| async move {
+ let location_task = editor.update(&mut cx, |editor, cx| {
+ project.update(cx, |project, cx| {
+ let language_server_name =
+ editor.buffer.read(cx).as_singleton().and_then(|buffer| {
+ project
+ .language_server_for_buffer(buffer.read(cx), server_id, cx)
+ .map(|(_, lsp_adapter)| {
+ LanguageServerName(Arc::from(lsp_adapter.name()))
+ })
+ });
+ language_server_name.map(|language_server_name| {
+ project.open_local_buffer_via_lsp(
+ lsp_location.uri.clone(),
+ server_id,
+ language_server_name,
+ cx,
+ )
+ })
+ })
+ })?;
+ let location = match location_task {
+ Some(task) => Some({
+ let target_buffer_handle = task.await.context("open local buffer")?;
+ let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
+ let target_start = target_buffer
+ .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
+ let target_end = target_buffer
+ .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
+ target_buffer.anchor_after(target_start)
+ ..target_buffer.anchor_before(target_end)
+ })?;
+ Location {
+ buffer: target_buffer_handle,
+ range,
+ }
+ }),
+ None => None,
+ };
+ Ok(location)
+ })
+ }
// pub fn find_all_references(
// workspace: &mut Workspace,
@@ -2,7 +2,8 @@ use crate::{
display_map::DisplaySnapshot,
element::PointForPosition,
hover_popover::{self, InlayHover},
- Anchor, DisplayPoint, Editor, EditorSnapshot, InlayId, SelectPhase,
+ Anchor, DisplayPoint, Editor, EditorSnapshot, GoToDefinition, GoToTypeDefinition, InlayId,
+ SelectPhase,
};
use gpui::{Task, ViewContext};
use language::{Bias, ToOffset};
@@ -108,61 +109,59 @@ pub fn update_go_to_definition_link(
shift_held: bool,
cx: &mut ViewContext<Editor>,
) {
- todo!("old version below");
-}
-// let pending_nonempty_selection = editor.has_pending_nonempty_selection();
-
-// // Store new mouse point as an anchor
-// let snapshot = editor.snapshot(cx);
-// let trigger_point = match origin {
-// Some(GoToDefinitionTrigger::Text(p)) => {
-// Some(TriggerPoint::Text(snapshot.buffer_snapshot.anchor_before(
-// p.to_offset(&snapshot.display_snapshot, Bias::Left),
-// )))
-// }
-// Some(GoToDefinitionTrigger::InlayHint(p, lsp_location, language_server_id)) => {
-// Some(TriggerPoint::InlayHint(p, lsp_location, language_server_id))
-// }
-// None => None,
-// };
-
-// // If the new point is the same as the previously stored one, return early
-// if let (Some(a), Some(b)) = (
-// &trigger_point,
-// &editor.link_go_to_definition_state.last_trigger_point,
-// ) {
-// match (a, b) {
-// (TriggerPoint::Text(anchor_a), TriggerPoint::Text(anchor_b)) => {
-// if anchor_a.cmp(anchor_b, &snapshot.buffer_snapshot).is_eq() {
-// return;
-// }
-// }
-// (TriggerPoint::InlayHint(range_a, _, _), TriggerPoint::InlayHint(range_b, _, _)) => {
-// if range_a == range_b {
-// return;
-// }
-// }
-// _ => {}
-// }
-// }
+ let pending_nonempty_selection = editor.has_pending_nonempty_selection();
+
+ // Store new mouse point as an anchor
+ let snapshot = editor.snapshot(cx);
+ let trigger_point = match origin {
+ Some(GoToDefinitionTrigger::Text(p)) => {
+ Some(TriggerPoint::Text(snapshot.buffer_snapshot.anchor_before(
+ p.to_offset(&snapshot.display_snapshot, Bias::Left),
+ )))
+ }
+ Some(GoToDefinitionTrigger::InlayHint(p, lsp_location, language_server_id)) => {
+ Some(TriggerPoint::InlayHint(p, lsp_location, language_server_id))
+ }
+ None => None,
+ };
+
+ // If the new point is the same as the previously stored one, return early
+ if let (Some(a), Some(b)) = (
+ &trigger_point,
+ &editor.link_go_to_definition_state.last_trigger_point,
+ ) {
+ match (a, b) {
+ (TriggerPoint::Text(anchor_a), TriggerPoint::Text(anchor_b)) => {
+ if anchor_a.cmp(anchor_b, &snapshot.buffer_snapshot).is_eq() {
+ return;
+ }
+ }
+ (TriggerPoint::InlayHint(range_a, _, _), TriggerPoint::InlayHint(range_b, _, _)) => {
+ if range_a == range_b {
+ return;
+ }
+ }
+ _ => {}
+ }
+ }
-// editor.link_go_to_definition_state.last_trigger_point = trigger_point.clone();
+ editor.link_go_to_definition_state.last_trigger_point = trigger_point.clone();
-// if pending_nonempty_selection {
-// hide_link_definition(editor, cx);
-// return;
-// }
+ if pending_nonempty_selection {
+ hide_link_definition(editor, cx);
+ return;
+ }
-// if cmd_held {
-// if let Some(trigger_point) = trigger_point {
-// let kind = trigger_point.definition_kind(shift_held);
-// show_link_definition(kind, editor, trigger_point, snapshot, cx);
-// return;
-// }
-// }
+ if cmd_held {
+ if let Some(trigger_point) = trigger_point {
+ let kind = trigger_point.definition_kind(shift_held);
+ show_link_definition(kind, editor, trigger_point, snapshot, cx);
+ return;
+ }
+ }
-// hide_link_definition(editor, cx);
-// }
+ hide_link_definition(editor, cx);
+}
pub fn update_inlay_link_and_hover_points(
snapshot: &DisplaySnapshot,
@@ -353,204 +352,202 @@ pub fn show_link_definition(
snapshot: EditorSnapshot,
cx: &mut ViewContext<Editor>,
) {
- todo!("old implementation below")
-}
-// let same_kind = editor.link_go_to_definition_state.kind == Some(definition_kind);
-// if !same_kind {
-// hide_link_definition(editor, cx);
-// }
-
-// if editor.pending_rename.is_some() {
-// return;
-// }
-
-// let trigger_anchor = trigger_point.anchor();
-// let (buffer, buffer_position) = if let Some(output) = editor
-// .buffer
-// .read(cx)
-// .text_anchor_for_position(trigger_anchor.clone(), cx)
-// {
-// output
-// } else {
-// return;
-// };
-
-// let excerpt_id = if let Some((excerpt_id, _, _)) = editor
-// .buffer()
-// .read(cx)
-// .excerpt_containing(trigger_anchor.clone(), cx)
-// {
-// excerpt_id
-// } else {
-// return;
-// };
+ let same_kind = editor.link_go_to_definition_state.kind == Some(definition_kind);
+ if !same_kind {
+ hide_link_definition(editor, cx);
+ }
-// let project = if let Some(project) = editor.project.clone() {
-// project
-// } else {
-// return;
-// };
+ if editor.pending_rename.is_some() {
+ return;
+ }
-// // Don't request again if the location is within the symbol region of a previous request with the same kind
-// if let Some(symbol_range) = &editor.link_go_to_definition_state.symbol_range {
-// if same_kind && symbol_range.point_within_range(&trigger_point, &snapshot) {
-// return;
-// }
-// }
+ let trigger_anchor = trigger_point.anchor();
+ let (buffer, buffer_position) = if let Some(output) = editor
+ .buffer
+ .read(cx)
+ .text_anchor_for_position(trigger_anchor.clone(), cx)
+ {
+ output
+ } else {
+ return;
+ };
+
+ let excerpt_id = if let Some((excerpt_id, _, _)) = editor
+ .buffer()
+ .read(cx)
+ .excerpt_containing(trigger_anchor.clone(), cx)
+ {
+ excerpt_id
+ } else {
+ return;
+ };
+
+ let project = if let Some(project) = editor.project.clone() {
+ project
+ } else {
+ return;
+ };
+
+ // Don't request again if the location is within the symbol region of a previous request with the same kind
+ if let Some(symbol_range) = &editor.link_go_to_definition_state.symbol_range {
+ if same_kind && symbol_range.point_within_range(&trigger_point, &snapshot) {
+ return;
+ }
+ }
-// let task = cx.spawn(|this, mut cx| {
-// async move {
-// let result = match &trigger_point {
-// TriggerPoint::Text(_) => {
-// // query the LSP for definition info
-// cx.update(|cx| {
-// project.update(cx, |project, cx| match definition_kind {
-// LinkDefinitionKind::Symbol => {
-// project.definition(&buffer, buffer_position, cx)
-// }
+ let task = cx.spawn(|this, mut cx| {
+ async move {
+ let result = match &trigger_point {
+ TriggerPoint::Text(_) => {
+ // query the LSP for definition info
+ project
+ .update(&mut cx, |project, cx| match definition_kind {
+ LinkDefinitionKind::Symbol => {
+ project.definition(&buffer, buffer_position, cx)
+ }
+
+ LinkDefinitionKind::Type => {
+ project.type_definition(&buffer, buffer_position, cx)
+ }
+ })?
+ .await
+ .ok()
+ .map(|definition_result| {
+ (
+ definition_result.iter().find_map(|link| {
+ link.origin.as_ref().map(|origin| {
+ let start = snapshot.buffer_snapshot.anchor_in_excerpt(
+ excerpt_id.clone(),
+ origin.range.start,
+ );
+ let end = snapshot.buffer_snapshot.anchor_in_excerpt(
+ excerpt_id.clone(),
+ origin.range.end,
+ );
+ RangeInEditor::Text(start..end)
+ })
+ }),
+ definition_result
+ .into_iter()
+ .map(GoToDefinitionLink::Text)
+ .collect(),
+ )
+ })
+ }
+ TriggerPoint::InlayHint(highlight, lsp_location, server_id) => Some((
+ Some(RangeInEditor::Inlay(highlight.clone())),
+ vec![GoToDefinitionLink::InlayHint(
+ lsp_location.clone(),
+ *server_id,
+ )],
+ )),
+ };
+
+ this.update(&mut cx, |this, cx| {
+ // Clear any existing highlights
+ this.clear_highlights::<LinkGoToDefinitionState>(cx);
+ this.link_go_to_definition_state.kind = Some(definition_kind);
+ this.link_go_to_definition_state.symbol_range = result
+ .as_ref()
+ .and_then(|(symbol_range, _)| symbol_range.clone());
+
+ if let Some((symbol_range, definitions)) = result {
+ this.link_go_to_definition_state.definitions = definitions.clone();
+
+ let buffer_snapshot = buffer.read(cx).snapshot();
+
+ // Only show highlight if there exists a definition to jump to that doesn't contain
+ // the current location.
+ let any_definition_does_not_contain_current_location =
+ definitions.iter().any(|definition| {
+ match &definition {
+ GoToDefinitionLink::Text(link) => {
+ if link.target.buffer == buffer {
+ let range = &link.target.range;
+ // Expand range by one character as lsp definition ranges include positions adjacent
+ // but not contained by the symbol range
+ let start = buffer_snapshot.clip_offset(
+ range
+ .start
+ .to_offset(&buffer_snapshot)
+ .saturating_sub(1),
+ Bias::Left,
+ );
+ let end = buffer_snapshot.clip_offset(
+ range.end.to_offset(&buffer_snapshot) + 1,
+ Bias::Right,
+ );
+ let offset = buffer_position.to_offset(&buffer_snapshot);
+ !(start <= offset && end >= offset)
+ } else {
+ true
+ }
+ }
+ GoToDefinitionLink::InlayHint(_, _) => true,
+ }
+ });
+
+ if any_definition_does_not_contain_current_location {
+ // todo!()
+ // // Highlight symbol using theme link definition highlight style
+ // let style = theme::current(cx).editor.link_definition;
+ // let highlight_range =
+ // symbol_range.unwrap_or_else(|| match &trigger_point {
+ // TriggerPoint::Text(trigger_anchor) => {
+ // let snapshot = &snapshot.buffer_snapshot;
+ // // If no symbol range returned from language server, use the surrounding word.
+ // let (offset_range, _) =
+ // snapshot.surrounding_word(*trigger_anchor);
+ // RangeInEditor::Text(
+ // snapshot.anchor_before(offset_range.start)
+ // ..snapshot.anchor_after(offset_range.end),
+ // )
+ // }
+ // TriggerPoint::InlayHint(highlight, _, _) => {
+ // RangeInEditor::Inlay(highlight.clone())
+ // }
+ // });
+
+ // match highlight_range {
+ // RangeInEditor::Text(text_range) => this
+ // .highlight_text::<LinkGoToDefinitionState>(
+ // vec![text_range],
+ // style,
+ // cx,
+ // ),
+ // RangeInEditor::Inlay(highlight) => this
+ // .highlight_inlays::<LinkGoToDefinitionState>(
+ // vec![highlight],
+ // style,
+ // cx,
+ // ),
+ // }
+ } else {
+ hide_link_definition(this, cx);
+ }
+ }
+ })?;
-// LinkDefinitionKind::Type => {
-// project.type_definition(&buffer, buffer_position, cx)
-// }
-// })
-// })
-// .await
-// .ok()
-// .map(|definition_result| {
-// (
-// definition_result.iter().find_map(|link| {
-// link.origin.as_ref().map(|origin| {
-// let start = snapshot
-// .buffer_snapshot
-// .anchor_in_excerpt(excerpt_id.clone(), origin.range.start);
-// let end = snapshot
-// .buffer_snapshot
-// .anchor_in_excerpt(excerpt_id.clone(), origin.range.end);
-// RangeInEditor::Text(start..end)
-// })
-// }),
-// definition_result
-// .into_iter()
-// .map(GoToDefinitionLink::Text)
-// .collect(),
-// )
-// })
-// }
-// TriggerPoint::InlayHint(highlight, lsp_location, server_id) => Some((
-// Some(RangeInEditor::Inlay(highlight.clone())),
-// vec![GoToDefinitionLink::InlayHint(
-// lsp_location.clone(),
-// *server_id,
-// )],
-// )),
-// };
+ Ok::<_, anyhow::Error>(())
+ }
+ .log_err()
+ });
-// this.update(&mut cx, |this, cx| {
-// // Clear any existing highlights
-// this.clear_highlights::<LinkGoToDefinitionState>(cx);
-// this.link_go_to_definition_state.kind = Some(definition_kind);
-// this.link_go_to_definition_state.symbol_range = result
-// .as_ref()
-// .and_then(|(symbol_range, _)| symbol_range.clone());
-
-// if let Some((symbol_range, definitions)) = result {
-// this.link_go_to_definition_state.definitions = definitions.clone();
-
-// let buffer_snapshot = buffer.read(cx).snapshot();
-
-// // Only show highlight if there exists a definition to jump to that doesn't contain
-// // the current location.
-// let any_definition_does_not_contain_current_location =
-// definitions.iter().any(|definition| {
-// match &definition {
-// GoToDefinitionLink::Text(link) => {
-// if link.target.buffer == buffer {
-// let range = &link.target.range;
-// // Expand range by one character as lsp definition ranges include positions adjacent
-// // but not contained by the symbol range
-// let start = buffer_snapshot.clip_offset(
-// range
-// .start
-// .to_offset(&buffer_snapshot)
-// .saturating_sub(1),
-// Bias::Left,
-// );
-// let end = buffer_snapshot.clip_offset(
-// range.end.to_offset(&buffer_snapshot) + 1,
-// Bias::Right,
-// );
-// let offset = buffer_position.to_offset(&buffer_snapshot);
-// !(start <= offset && end >= offset)
-// } else {
-// true
-// }
-// }
-// GoToDefinitionLink::InlayHint(_, _) => true,
-// }
-// });
-
-// if any_definition_does_not_contain_current_location {
-// // todo!()
-// // // Highlight symbol using theme link definition highlight style
-// // let style = theme::current(cx).editor.link_definition;
-// // let highlight_range =
-// // symbol_range.unwrap_or_else(|| match &trigger_point {
-// // TriggerPoint::Text(trigger_anchor) => {
-// // let snapshot = &snapshot.buffer_snapshot;
-// // // If no symbol range returned from language server, use the surrounding word.
-// // let (offset_range, _) =
-// // snapshot.surrounding_word(*trigger_anchor);
-// // RangeInEditor::Text(
-// // snapshot.anchor_before(offset_range.start)
-// // ..snapshot.anchor_after(offset_range.end),
-// // )
-// // }
-// // TriggerPoint::InlayHint(highlight, _, _) => {
-// // RangeInEditor::Inlay(highlight.clone())
-// // }
-// // });
-
-// // match highlight_range {
-// // RangeInEditor::Text(text_range) => this
-// // .highlight_text::<LinkGoToDefinitionState>(
-// // vec![text_range],
-// // style,
-// // cx,
-// // ),
-// // RangeInEditor::Inlay(highlight) => this
-// // .highlight_inlays::<LinkGoToDefinitionState>(
-// // vec![highlight],
-// // style,
-// // cx,
-// // ),
-// // }
-// } else {
-// hide_link_definition(this, cx);
-// }
-// }
-// })?;
+ editor.link_go_to_definition_state.task = Some(task);
+}
-// Ok::<_, anyhow::Error>(())
-// }
-// .log_err()
-// });
+pub fn hide_link_definition(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
+ if editor.link_go_to_definition_state.symbol_range.is_some()
+ || !editor.link_go_to_definition_state.definitions.is_empty()
+ {
+ editor.link_go_to_definition_state.symbol_range.take();
+ editor.link_go_to_definition_state.definitions.clear();
+ cx.notify();
+ }
-// editor.link_go_to_definition_state.task = Some(task);
-// }
+ editor.link_go_to_definition_state.task = None;
-pub fn hide_link_definition(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
- todo!()
- // if editor.link_go_to_definition_state.symbol_range.is_some()
- // || !editor.link_go_to_definition_state.definitions.is_empty()
- // {
- // editor.link_go_to_definition_state.symbol_range.take();
- // editor.link_go_to_definition_state.definitions.clear();
- // cx.notify();
- // }
-
- // editor.link_go_to_definition_state.task = None;
-
- // editor.clear_highlights::<LinkGoToDefinitionState>(cx);
+ editor.clear_highlights::<LinkGoToDefinitionState>(cx);
}
pub fn go_to_fetched_definition(
@@ -578,35 +575,34 @@ fn go_to_fetched_definition_of_kind(
split: bool,
cx: &mut ViewContext<Editor>,
) {
- todo!();
- // let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
- // hide_link_definition(editor, cx);
- // let cached_definitions_kind = editor.link_go_to_definition_state.kind;
-
- // let is_correct_kind = cached_definitions_kind == Some(kind);
- // if !cached_definitions.is_empty() && is_correct_kind {
- // if !editor.focused {
- // cx.focus_self();
- // }
-
- // editor.navigate_to_definitions(cached_definitions, split, cx);
- // } else {
- // editor.select(
- // SelectPhase::Begin {
- // position: point.next_valid,
- // add: false,
- // click_count: 1,
- // },
- // cx,
- // );
-
- // if point.as_valid().is_some() {
- // match kind {
- // LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx),
- // LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx),
- // }
- // }
- // }
+ let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
+ hide_link_definition(editor, cx);
+ let cached_definitions_kind = editor.link_go_to_definition_state.kind;
+
+ let is_correct_kind = cached_definitions_kind == Some(kind);
+ if !cached_definitions.is_empty() && is_correct_kind {
+ if !editor.focused {
+ cx.focus(&editor.focus_handle);
+ }
+
+ editor.navigate_to_definitions(cached_definitions, split, cx);
+ } else {
+ editor.select(
+ SelectPhase::Begin {
+ position: point.next_valid,
+ add: false,
+ click_count: 1,
+ },
+ cx,
+ );
+
+ if point.as_valid().is_some() {
+ match kind {
+ LinkDefinitionKind::Symbol => editor.go_to_definition(&GoToDefinition, cx),
+ LinkDefinitionKind::Type => editor.go_to_type_definition(&GoToTypeDefinition, cx),
+ }
+ }
+ }
}
// #[cfg(test)]