aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/references.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/references.rs')
-rw-r--r--crates/ra_ide_api/src/references.rs66
1 files changed, 53 insertions, 13 deletions
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index 1c9491a0a..b129f3134 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -1,13 +1,10 @@
1use relative_path::RelativePathBuf; 1use relative_path::{RelativePath, RelativePathBuf};
2 2use hir::{ModuleSource, source_binder};
3use hir::{ 3use ra_db::{FileId, SourceDatabase};
4 self, ModuleSource, source_binder::module_from_declaration,
5};
6use ra_syntax::{ 4use ra_syntax::{
5 AstNode, SyntaxNode, TextRange, SourceFile,
6 ast::{self, NameOwner},
7 algo::find_node_at_offset, 7 algo::find_node_at_offset,
8 ast,
9 AstNode,
10 SyntaxNode
11}; 8};
12 9
13use crate::{ 10use crate::{
@@ -17,8 +14,51 @@ use crate::{
17 SourceChange, 14 SourceChange,
18 SourceFileEdit, 15 SourceFileEdit,
19}; 16};
20use ra_db::SourceDatabase; 17
21use relative_path::RelativePath; 18pub(crate) fn find_all_refs(db: &RootDatabase, position: FilePosition) -> Vec<(FileId, TextRange)> {
19 let file = db.parse(position.file_id);
20 // Find the binding associated with the offset
21 let (binding, descr) = match find_binding(db, &file, position) {
22 None => return Vec::new(),
23 Some(it) => it,
24 };
25
26 let mut ret = binding
27 .name()
28 .into_iter()
29 .map(|name| (position.file_id, name.syntax().range()))
30 .collect::<Vec<_>>();
31 ret.extend(
32 descr
33 .scopes(db)
34 .find_all_refs(binding)
35 .into_iter()
36 .map(|ref_desc| (position.file_id, ref_desc.range)),
37 );
38
39 return ret;
40
41 fn find_binding<'a>(
42 db: &RootDatabase,
43 source_file: &'a SourceFile,
44 position: FilePosition,
45 ) -> Option<(&'a ast::BindPat, hir::Function)> {
46 let syntax = source_file.syntax();
47 if let Some(binding) = find_node_at_offset::<ast::BindPat>(syntax, position.offset) {
48 let descr =
49 source_binder::function_from_child_node(db, position.file_id, binding.syntax())?;
50 return Some((binding, descr));
51 };
52 let name_ref = find_node_at_offset::<ast::NameRef>(syntax, position.offset)?;
53 let descr =
54 source_binder::function_from_child_node(db, position.file_id, name_ref.syntax())?;
55 let scope = descr.scopes(db);
56 let resolved = scope.resolve_local_name(name_ref)?;
57 let resolved = resolved.ptr().to_node(source_file);
58 let binding = find_node_at_offset::<ast::BindPat>(syntax, resolved.range().end())?;
59 Some((binding, descr))
60 }
61}
22 62
23pub(crate) fn rename( 63pub(crate) fn rename(
24 db: &RootDatabase, 64 db: &RootDatabase,
@@ -57,7 +97,8 @@ fn rename_mod(
57) -> Option<SourceChange> { 97) -> Option<SourceChange> {
58 let mut source_file_edits = Vec::new(); 98 let mut source_file_edits = Vec::new();
59 let mut file_system_edits = Vec::new(); 99 let mut file_system_edits = Vec::new();
60 if let Some(module) = module_from_declaration(db, position.file_id, &ast_module) { 100 if let Some(module) = source_binder::module_from_declaration(db, position.file_id, &ast_module)
101 {
61 let (file_id, module_source) = module.definition_source(db); 102 let (file_id, module_source) = module.definition_source(db);
62 match module_source { 103 match module_source {
63 ModuleSource::SourceFile(..) => { 104 ModuleSource::SourceFile(..) => {
@@ -108,8 +149,7 @@ fn rename_reference(
108 position: FilePosition, 149 position: FilePosition,
109 new_name: &str, 150 new_name: &str,
110) -> Option<SourceChange> { 151) -> Option<SourceChange> {
111 let edit = db 152 let edit = find_all_refs(db, position)
112 .find_all_refs(position)
113 .iter() 153 .iter()
114 .map(|(file_id, text_range)| SourceFileEdit { 154 .map(|(file_id, text_range)| SourceFileEdit {
115 file_id: *file_id, 155 file_id: *file_id,