Add a way to control go to definition fallback (#27426)
Follow-up of https://github.com/zed-industries/zed/pull/9243 and https://github.com/zed-industries/zed/pull/16512 Release Notes: - Added a way to control go to definition fallback
This commit is contained in:
parent
8c8f50d916
commit
30f7e896cf
5 changed files with 107 additions and 7 deletions
|
@ -60,6 +60,7 @@ use collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
|||
use convert_case::{Case, Casing};
|
||||
use display_map::*;
|
||||
pub use display_map::{DisplayPoint, FoldPlaceholder};
|
||||
use editor_settings::GoToDefinitionFallback;
|
||||
pub use editor_settings::{
|
||||
CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine, SearchSettings, ShowScrollbar,
|
||||
};
|
||||
|
@ -12662,15 +12663,21 @@ impl Editor {
|
|||
) -> Task<Result<Navigated>> {
|
||||
let definition =
|
||||
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
|
||||
let fallback_strategy = EditorSettings::get_global(cx).go_to_definition_fallback;
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
if definition.await? == Navigated::Yes {
|
||||
return Ok(Navigated::Yes);
|
||||
}
|
||||
match editor.update_in(cx, |editor, window, cx| {
|
||||
editor.find_all_references(&FindAllReferences, window, cx)
|
||||
})? {
|
||||
Some(references) => references.await,
|
||||
None => Ok(Navigated::No),
|
||||
match fallback_strategy {
|
||||
GoToDefinitionFallback::None => Ok(Navigated::No),
|
||||
GoToDefinitionFallback::FindAllReferences => {
|
||||
match editor.update_in(cx, |editor, window, cx| {
|
||||
editor.find_all_references(&FindAllReferences, window, cx)
|
||||
})? {
|
||||
Some(references) => references.await,
|
||||
None => Ok(Navigated::No),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ pub struct EditorSettings {
|
|||
pub search: SearchSettings,
|
||||
pub auto_signature_help: bool,
|
||||
pub show_signature_help_after_edits: bool,
|
||||
#[serde(default)]
|
||||
pub go_to_definition_fallback: GoToDefinitionFallback,
|
||||
pub jupyter: Jupyter,
|
||||
}
|
||||
|
||||
|
@ -211,6 +213,17 @@ pub struct SearchSettings {
|
|||
pub regex: bool,
|
||||
}
|
||||
|
||||
/// What to do when go to definition yields no results.
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum GoToDefinitionFallback {
|
||||
/// Disables the fallback.
|
||||
None,
|
||||
/// Looks up references of the same symbol instead.
|
||||
#[default]
|
||||
FindAllReferences,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct EditorSettingsContent {
|
||||
/// Whether the cursor blinks in the editor.
|
||||
|
@ -330,6 +343,13 @@ pub struct EditorSettingsContent {
|
|||
/// Default: false
|
||||
pub show_signature_help_after_edits: Option<bool>,
|
||||
|
||||
/// Whether to follow-up empty go to definition responses from the language server or not.
|
||||
/// `FindAllReferences` allows to look up references of the same symbol instead.
|
||||
/// `None` disables the fallback.
|
||||
///
|
||||
/// Default: FindAllReferences
|
||||
pub go_to_definition_fallback: Option<GoToDefinitionFallback>,
|
||||
|
||||
/// Jupyter REPL settings.
|
||||
pub jupyter: Option<JupyterContent>,
|
||||
}
|
||||
|
|
|
@ -16434,6 +16434,69 @@ async fn test_goto_definition_with_find_all_references_fallback(cx: &mut TestApp
|
|||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_goto_definition_no_fallback(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
cx.update(|cx| {
|
||||
let mut editor_settings = EditorSettings::get_global(cx).clone();
|
||||
editor_settings.go_to_definition_fallback = GoToDefinitionFallback::None;
|
||||
EditorSettings::override_global(editor_settings, cx);
|
||||
});
|
||||
let mut cx = EditorLspTestContext::new_rust(
|
||||
lsp::ServerCapabilities {
|
||||
definition_provider: Some(lsp::OneOf::Left(true)),
|
||||
references_provider: Some(lsp::OneOf::Left(true)),
|
||||
..lsp::ServerCapabilities::default()
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
let original_state = r#"fn one() {
|
||||
let mut a = ˇtwo();
|
||||
}
|
||||
|
||||
fn two() {}"#
|
||||
.unindent();
|
||||
cx.set_state(&original_state);
|
||||
|
||||
let mut go_to_definition = cx
|
||||
.lsp
|
||||
.set_request_handler::<lsp::request::GotoDefinition, _, _>(
|
||||
move |_, _| async move { Ok(None) },
|
||||
);
|
||||
let _references = cx
|
||||
.lsp
|
||||
.set_request_handler::<lsp::request::References, _, _>(move |_, _| async move {
|
||||
panic!("Should not call for references with no go to definition fallback")
|
||||
});
|
||||
|
||||
let navigated = cx
|
||||
.update_editor(|editor, window, cx| editor.go_to_definition(&GoToDefinition, window, cx))
|
||||
.await
|
||||
.expect("Failed to navigate to lookup references");
|
||||
go_to_definition
|
||||
.next()
|
||||
.await
|
||||
.expect("Should have called the go_to_definition handler");
|
||||
|
||||
assert_eq!(
|
||||
navigated,
|
||||
Navigated::No,
|
||||
"Should have navigated to references as a fallback after empty GoToDefinition response"
|
||||
);
|
||||
cx.assert_editor_state(&original_state);
|
||||
let editors = cx.update_workspace(|workspace, _, cx| {
|
||||
workspace.items_of_type::<Editor>(cx).collect::<Vec<_>>()
|
||||
});
|
||||
cx.update_editor(|_, _, _| {
|
||||
assert_eq!(
|
||||
editors.len(),
|
||||
1,
|
||||
"After unsuccessful fallback, no other editor should have been opened"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_find_enclosing_node_with_task(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
editor_settings::MultiCursorModifier,
|
||||
editor_settings::{GoToDefinitionFallback, MultiCursorModifier},
|
||||
hover_popover::{self, InlayHover},
|
||||
scroll::ScrollAmount,
|
||||
Anchor, Editor, EditorSettings, EditorSnapshot, FindAllReferences, GoToDefinition,
|
||||
|
@ -174,7 +174,12 @@ impl Editor {
|
|||
if definition_revealed == Navigated::Yes {
|
||||
return None;
|
||||
}
|
||||
editor.find_all_references(&FindAllReferences, window, cx)
|
||||
match EditorSettings::get_global(cx).go_to_definition_fallback {
|
||||
GoToDefinitionFallback::None => None,
|
||||
GoToDefinitionFallback::FindAllReferences => {
|
||||
editor.find_all_references(&FindAllReferences, window, cx)
|
||||
}
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.flatten();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue