diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide/src/lib.rs | 17 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 82 |
2 files changed, 56 insertions, 43 deletions
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 4763c0aac..286a6a110 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -56,7 +56,7 @@ use ide_db::{ | |||
56 | symbol_index::{self, FileSymbol}, | 56 | symbol_index::{self, FileSymbol}, |
57 | LineIndexDatabase, | 57 | LineIndexDatabase, |
58 | }; | 58 | }; |
59 | use syntax::{SourceFile, TextRange, TextSize}; | 59 | use syntax::{SourceFile, SyntaxKind, TextRange, TextSize}; |
60 | 60 | ||
61 | use crate::display::ToNav; | 61 | use crate::display::ToNav; |
62 | 62 | ||
@@ -369,6 +369,21 @@ impl Analysis { | |||
369 | }) | 369 | }) |
370 | } | 370 | } |
371 | 371 | ||
372 | /// Finds all methods and free functions for the file. | ||
373 | pub fn find_all_methods(&self, file_id: FileId) -> Cancelable<Vec<FileRange>> { | ||
374 | let res = self | ||
375 | .file_structure(file_id)? | ||
376 | .into_iter() | ||
377 | .filter(|it| match it.kind { | ||
378 | SyntaxKind::FN => true, | ||
379 | _ => false, | ||
380 | }) | ||
381 | .filter_map(|it| Some(FileRange { file_id, range: it.navigation_range })) | ||
382 | .collect(); | ||
383 | |||
384 | Ok(res) | ||
385 | } | ||
386 | |||
372 | /// Returns a short text describing element at position. | 387 | /// Returns a short text describing element at position. |
373 | pub fn hover( | 388 | pub fn hover( |
374 | &self, | 389 | &self, |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 06afb8148..1a0bee5e4 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -955,48 +955,18 @@ pub(crate) fn handle_code_lens( | |||
955 | } | 955 | } |
956 | 956 | ||
957 | if snap.config.lens.references() { | 957 | if snap.config.lens.references() { |
958 | let ref_lenses = snap | 958 | lenses.extend(snap.analysis.find_all_methods(file_id)?.into_iter().map(|it| { |
959 | .analysis | 959 | let range = to_proto::range(&line_index, it.range); |
960 | .file_structure(file_id)? | 960 | let position = to_proto::position(&line_index, it.range.start()); |
961 | .into_iter() | 961 | let lens_params = |
962 | .filter(|it| match it.kind { | 962 | lsp_types::TextDocumentPositionParams::new(params.text_document.clone(), position); |
963 | SyntaxKind::FN => true, | 963 | |
964 | _ => false, | 964 | CodeLens { |
965 | }) | 965 | range, |
966 | .filter_map(|it| { | 966 | command: None, |
967 | let position = FilePosition { file_id, offset: it.navigation_range.start() }; | 967 | data: Some(to_value(CodeLensResolveData::References(lens_params)).unwrap()), |
968 | let scope = None; // all references | 968 | } |
969 | 969 | })); | |
970 | snap.analysis.find_all_refs(position, scope).unwrap_or(None).map(|r| { | ||
971 | let mut lenses = Vec::new(); | ||
972 | if r.len() == 1 { | ||
973 | // Only a declaration | ||
974 | return lenses; | ||
975 | } | ||
976 | |||
977 | let uri = to_proto::url(&snap, file_id); | ||
978 | let range = to_proto::range(&line_index, it.node_range); | ||
979 | let position = to_proto::position(&line_index, position.offset); | ||
980 | |||
981 | if snap.config.lens.method_refs { | ||
982 | let all_locations: Vec<_> = r | ||
983 | .references() | ||
984 | .iter() | ||
985 | .filter_map(|it| to_proto::location(&snap, it.file_range).ok()) | ||
986 | .collect(); | ||
987 | let title = reference_title(all_locations.len()); | ||
988 | let all_refs = | ||
989 | show_references_command(title, &uri, position, all_locations); | ||
990 | lenses.push(CodeLens { range, command: Some(all_refs), data: None }); | ||
991 | } | ||
992 | |||
993 | lenses | ||
994 | }) | ||
995 | }) | ||
996 | .flatten() | ||
997 | .collect_vec(); | ||
998 | |||
999 | lenses.extend(ref_lenses); | ||
1000 | } | 970 | } |
1001 | 971 | ||
1002 | Ok(Some(lenses)) | 972 | Ok(Some(lenses)) |
@@ -1006,6 +976,7 @@ pub(crate) fn handle_code_lens( | |||
1006 | #[serde(rename_all = "camelCase")] | 976 | #[serde(rename_all = "camelCase")] |
1007 | enum CodeLensResolveData { | 977 | enum CodeLensResolveData { |
1008 | Impls(lsp_types::request::GotoImplementationParams), | 978 | Impls(lsp_types::request::GotoImplementationParams), |
979 | References(lsp_types::TextDocumentPositionParams), | ||
1009 | } | 980 | } |
1010 | 981 | ||
1011 | pub(crate) fn handle_code_lens_resolve( | 982 | pub(crate) fn handle_code_lens_resolve( |
@@ -1037,6 +1008,33 @@ pub(crate) fn handle_code_lens_resolve( | |||
1037 | ); | 1008 | ); |
1038 | Ok(CodeLens { range: code_lens.range, command: Some(cmd), data: None }) | 1009 | Ok(CodeLens { range: code_lens.range, command: Some(cmd), data: None }) |
1039 | } | 1010 | } |
1011 | Some(CodeLensResolveData::References(doc_position)) => { | ||
1012 | let position = from_proto::file_position(&snap, doc_position.clone())?; | ||
1013 | let locations = snap | ||
1014 | .analysis | ||
1015 | .find_all_refs(position, None) | ||
1016 | .unwrap_or(None) | ||
1017 | .map(|r| { | ||
1018 | r.references() | ||
1019 | .iter() | ||
1020 | .filter_map(|it| to_proto::location(&snap, it.file_range).ok()) | ||
1021 | .collect_vec() | ||
1022 | }) | ||
1023 | .unwrap_or_default(); | ||
1024 | |||
1025 | let cmd = if locations.is_empty() { | ||
1026 | Command { title: "No references".into(), command: "".into(), arguments: None } | ||
1027 | } else { | ||
1028 | show_references_command( | ||
1029 | reference_title(locations.len()), | ||
1030 | &doc_position.text_document.uri, | ||
1031 | code_lens.range.start, | ||
1032 | locations, | ||
1033 | ) | ||
1034 | }; | ||
1035 | |||
1036 | Ok(CodeLens { range: code_lens.range, command: Some(cmd), data: None }) | ||
1037 | } | ||
1040 | None => Ok(CodeLens { | 1038 | None => Ok(CodeLens { |
1041 | range: code_lens.range, | 1039 | range: code_lens.range, |
1042 | command: Some(Command { title: "Error".into(), ..Default::default() }), | 1040 | command: Some(Command { title: "Error".into(), ..Default::default() }), |