From 07394316ff0c5454b3a9e854945ebd29b90259ec Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 4 Jun 2021 15:49:43 +0200 Subject: [PATCH] Add function references hover action --- crates/ide/src/hover.rs | 29 +++++++++++++++++++++++++- crates/rust-analyzer/src/config.rs | 4 ++++ crates/rust-analyzer/src/handlers.rs | 31 ++++++++++++++++++++++++++++ docs/user/generated_config.adoc | 6 ++++++ editors/code/package.json | 5 +++++ editors/code/src/config.ts | 1 + 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 04598cd068..455a27e488 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -28,6 +28,7 @@ use crate::{ #[derive(Clone, Debug, PartialEq, Eq)] pub struct HoverConfig { pub implementations: bool, + pub references: bool, pub run: bool, pub debug: bool, pub goto_type_def: bool, @@ -38,6 +39,7 @@ pub struct HoverConfig { impl HoverConfig { pub const NO_ACTIONS: Self = Self { implementations: false, + references: false, run: false, debug: false, goto_type_def: false, @@ -46,7 +48,7 @@ impl HoverConfig { }; pub fn any(&self) -> bool { - self.implementations || self.runnable() || self.goto_type_def + self.implementations || self.references || self.runnable() || self.goto_type_def } pub fn none(&self) -> bool { @@ -62,6 +64,7 @@ impl HoverConfig { pub enum HoverAction { Runnable(Runnable), Implementation(FilePosition), + Reference(FilePosition), GoToType(Vec), } @@ -148,6 +151,10 @@ pub(crate) fn hover( res.actions.push(action); } + if let Some(action) = show_fn_references_action(db, definition) { + res.actions.push(action); + } + if let Some(action) = runnable_action(&sema, definition, position.file_id) { res.actions.push(action); } @@ -211,6 +218,18 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option Option { + match def { + Definition::ModuleDef(ModuleDef::Function(it)) => it.try_to_nav(db).map(|nav_target| { + HoverAction::Reference(FilePosition { + file_id: nav_target.file_id, + offset: nav_target.focus_or_full_range().start(), + }) + }), + _ => None, + } +} + fn runnable_action( sema: &Semantics, def: Definition, @@ -2377,6 +2396,14 @@ fn foo_$0test() {} "#, expect![[r#" [ + Reference( + FilePosition { + file_id: FileId( + 0, + ), + offset: 11, + }, + ), Runnable( Runnable { nav: NavigationTarget { diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index d1f3c1b06f..3b20d741a0 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -152,6 +152,9 @@ config_data! { /// Whether to show `Implementations` action. Only applies when /// `#rust-analyzer.hoverActions.enable#` is set. hoverActions_implementations: bool = "true", + /// Whether to show `References` action. Only applies when + /// `#rust-analyzer.hoverActions.enable#` is set. + hoverActions_references: bool = "false", /// Whether to show `Run` action. Only applies when /// `#rust-analyzer.hoverActions.enable#` is set. hoverActions_run: bool = "true", @@ -719,6 +722,7 @@ impl Config { HoverConfig { implementations: self.data.hoverActions_enable && self.data.hoverActions_implementations, + references: self.data.hoverActions_enable && self.data.hoverActions_references, run: self.data.hoverActions_enable && self.data.hoverActions_run, debug: self.data.hoverActions_enable && self.data.hoverActions_debug, goto_type_def: self.data.hoverActions_enable && self.data.hoverActions_gotoTypeDef, diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 49ee4b9224..70511c5caf 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1506,6 +1506,36 @@ fn show_impl_command_link( None } +fn show_ref_command_link( + snap: &GlobalStateSnapshot, + position: &FilePosition, +) -> Option { + if snap.config.hover().implementations { + if let Some(ref_search_res) = snap.analysis.find_all_refs(*position, None).unwrap_or(None) { + let uri = to_proto::url(snap, position.file_id); + let line_index = snap.file_line_index(position.file_id).ok()?; + let position = to_proto::position(&line_index, position.offset); + let locations: Vec<_> = ref_search_res + .references + .into_iter() + .flat_map(|(file_id, ranges)| { + ranges.into_iter().filter_map(move |(range, _)| { + to_proto::location(snap, FileRange { file_id, range }).ok() + }) + }) + .collect(); + let title = to_proto::reference_title(locations.len()); + let command = to_proto::command::show_references(title, &uri, position, locations); + + return Some(lsp_ext::CommandLinkGroup { + commands: vec![to_command_link(command, "Go to references".into())], + ..Default::default() + }); + } + } + None +} + fn runnable_action_links( snap: &GlobalStateSnapshot, runnable: Runnable, @@ -1566,6 +1596,7 @@ fn prepare_hover_actions( .iter() .filter_map(|it| match it { HoverAction::Implementation(position) => show_impl_command_link(snap, position), + HoverAction::Reference(position) => show_ref_command_link(snap, position), HoverAction::Runnable(r) => runnable_action_links(snap, r.clone()), HoverAction::GoToType(targets) => goto_type_action_links(snap, targets), }) diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 4eec8455df..34a91486b3 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -228,6 +228,12 @@ Whether to show `Go to Type Definition` action. Only applies when Whether to show `Implementations` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set. -- +[[rust-analyzer.hoverActions.references]]rust-analyzer.hoverActions.references (default: `false`):: ++ +-- +Whether to show `References` action. Only applies when +`#rust-analyzer.hoverActions.enable#` is set. +-- [[rust-analyzer.hoverActions.run]]rust-analyzer.hoverActions.run (default: `true`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index bffc1e05b7..0f3ed48a0e 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -660,6 +660,11 @@ "default": true, "type": "boolean" }, + "rust-analyzer.hoverActions.references": { + "markdownDescription": "Whether to show `References` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.", + "default": false, + "type": "boolean" + }, "rust-analyzer.hoverActions.run": { "markdownDescription": "Whether to show `Run` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.", "default": true, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index d3d6e631a0..1f1fe59a41 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -165,6 +165,7 @@ export class Config { return { enable: this.get("hoverActions.enable"), implementations: this.get("hoverActions.implementations"), + references: this.get("hoverActions.references"), run: this.get("hoverActions.run"), debug: this.get("hoverActions.debug"), gotoTypeDef: this.get("hoverActions.gotoTypeDef"),