Add method references CodeLens

This commit is contained in:
vsrs 2020-09-01 16:33:02 +03:00
parent e813de6cdd
commit eeb40dbece
4 changed files with 74 additions and 8 deletions

View file

@ -74,19 +74,18 @@ pub struct LensConfig {
pub run: bool, pub run: bool,
pub debug: bool, pub debug: bool,
pub implementations: bool, pub implementations: bool,
pub method_refs: bool,
} }
impl Default for LensConfig { impl Default for LensConfig {
fn default() -> Self { fn default() -> Self {
Self { run: true, debug: true, implementations: true } Self { run: true, debug: true, implementations: true, method_refs: true }
} }
} }
impl LensConfig { impl LensConfig {
pub const NO_LENS: LensConfig = Self { run: false, debug: false, implementations: false };
pub fn any(&self) -> bool { pub fn any(&self) -> bool {
self.implementations || self.runnable() self.implementations || self.runnable() || self.references()
} }
pub fn none(&self) -> bool { pub fn none(&self) -> bool {
@ -96,6 +95,10 @@ impl LensConfig {
pub fn runnable(&self) -> bool { pub fn runnable(&self) -> bool {
self.run || self.debug self.run || self.debug
} }
pub fn references(&self) -> bool {
self.method_refs
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -278,6 +281,7 @@ impl Config {
run: data.lens_enable && data.lens_run, run: data.lens_enable && data.lens_run,
debug: data.lens_enable && data.lens_debug, debug: data.lens_enable && data.lens_debug,
implementations: data.lens_enable && data.lens_implementations, implementations: data.lens_enable && data.lens_implementations,
method_refs: data.lens_enable && data.lens_methodReferences,
}; };
if !data.linkedProjects.is_empty() { if !data.linkedProjects.is_empty() {
@ -463,6 +467,7 @@ config_data! {
lens_enable: bool = true, lens_enable: bool = true,
lens_implementations: bool = true, lens_implementations: bool = true,
lens_run: bool = true, lens_run: bool = true,
lens_methodReferences: bool = true,
linkedProjects: Vec<ManifestOrProjectJson> = Vec::new(), linkedProjects: Vec<ManifestOrProjectJson> = Vec::new(),
lruCapacity: Option<usize> = None, lruCapacity: Option<usize> = None,

View file

@ -11,6 +11,7 @@ use ide::{
FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query,
RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit,
}; };
use itertools::Itertools;
use lsp_server::ErrorCode; use lsp_server::ErrorCode;
use lsp_types::{ use lsp_types::{
CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
@ -952,6 +953,52 @@ pub(crate) fn handle_code_lens(
}), }),
); );
} }
if snap.config.lens.references() {
let ref_lenses = snap
.analysis
.file_structure(file_id)?
.into_iter()
.filter(|it| match it.kind {
SyntaxKind::FN => true,
_ => false,
})
.filter_map(|it| {
let position = FilePosition { file_id, offset: it.navigation_range.start() };
let scope = None; // all references
snap.analysis.find_all_refs(position, scope).unwrap_or(None).map(|r| {
let mut lenses = Vec::new();
if r.len() == 1 {
// Only a declaration
return lenses;
}
let uri = to_proto::url(&snap, file_id);
let range = to_proto::range(&line_index, it.node_range);
let position = to_proto::position(&line_index, position.offset);
if snap.config.lens.method_refs {
let all_locations: Vec<_> = r
.references()
.iter()
.filter_map(|it| to_proto::location(&snap, it.file_range).ok())
.collect();
let title = reference_title(all_locations.len());
let all_refs =
show_references_command(title, &uri, position, all_locations);
lenses.push(CodeLens { range, command: Some(all_refs), data: None });
}
lenses
})
})
.flatten()
.collect_vec();
lenses.extend(ref_lenses);
}
Ok(Some(lenses)) Ok(Some(lenses))
} }
@ -1248,6 +1295,14 @@ fn implementation_title(count: usize) -> String {
} }
} }
fn reference_title(count: usize) -> String {
if count == 1 {
"1 reference".into()
} else {
format!("{} references", count)
}
}
fn show_references_command( fn show_references_command(
title: String, title: String,
uri: &lsp_types::Url, uri: &lsp_types::Url,

View file

@ -554,6 +554,11 @@
"type": "boolean", "type": "boolean",
"default": true "default": true
}, },
"rust-analyzer.lens.methodReferences": {
"markdownDescription": "Whether to show `Method References` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
"type": "boolean",
"default": true
},
"rust-analyzer.hoverActions.enable": { "rust-analyzer.hoverActions.enable": {
"description": "Whether to show HoverActions in Rust files.", "description": "Whether to show HoverActions in Rust files.",
"type": "boolean", "type": "boolean",

View file

@ -138,6 +138,7 @@ export class Config {
run: this.get<boolean>("lens.run"), run: this.get<boolean>("lens.run"),
debug: this.get<boolean>("lens.debug"), debug: this.get<boolean>("lens.debug"),
implementations: this.get<boolean>("lens.implementations"), implementations: this.get<boolean>("lens.implementations"),
methodReferences: this.get<boolean>("lens.methodReferences"),
}; };
} }