aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/references
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/references')
-rw-r--r--crates/ra_ide_api/src/references/rename.rs6
-rw-r--r--crates/ra_ide_api/src/references/search_scope.rs87
2 files changed, 72 insertions, 21 deletions
diff --git a/crates/ra_ide_api/src/references/rename.rs b/crates/ra_ide_api/src/references/rename.rs
index 0e2e088e0..ee6e73e1b 100644
--- a/crates/ra_ide_api/src/references/rename.rs
+++ b/crates/ra_ide_api/src/references/rename.rs
@@ -110,7 +110,7 @@ fn rename_reference(
110 position: FilePosition, 110 position: FilePosition,
111 new_name: &str, 111 new_name: &str,
112) -> Option<RangeInfo<SourceChange>> { 112) -> Option<RangeInfo<SourceChange>> {
113 let RangeInfo { range, info: refs } = find_all_refs(db, position)?; 113 let RangeInfo { range, info: refs } = find_all_refs(db, position, None)?;
114 114
115 let edit = refs 115 let edit = refs
116 .into_iter() 116 .into_iter()
@@ -255,13 +255,13 @@ mod tests {
255 "#; 255 "#;
256 256
257 let (analysis, pos) = analysis_and_position(code); 257 let (analysis, pos) = analysis_and_position(code);
258 let refs = analysis.find_all_refs(pos).unwrap().unwrap(); 258 let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
259 assert_eq!(refs.len(), 3); 259 assert_eq!(refs.len(), 3);
260 } 260 }
261 261
262 fn get_all_refs(text: &str) -> ReferenceSearchResult { 262 fn get_all_refs(text: &str) -> ReferenceSearchResult {
263 let (analysis, position) = single_file_with_position(text); 263 let (analysis, position) = single_file_with_position(text);
264 analysis.find_all_refs(position).unwrap().unwrap() 264 analysis.find_all_refs(position, None).unwrap().unwrap()
265 } 265 }
266 266
267 #[test] 267 #[test]
diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs
index 21e667c83..b6eb248b7 100644
--- a/crates/ra_ide_api/src/references/search_scope.rs
+++ b/crates/ra_ide_api/src/references/search_scope.rs
@@ -2,33 +2,84 @@
2//! For `pub(crate)` things it's a crate, for `pub` things it's a crate and dependant crates. 2//! For `pub(crate)` things it's a crate, for `pub` things it's a crate and dependant crates.
3//! In some cases, the location of the references is known to within a `TextRange`, 3//! In some cases, the location of the references is known to within a `TextRange`,
4//! e.g. for things like local variables. 4//! e.g. for things like local variables.
5use std::mem;
5 6
6use hir::{DefWithBody, HasSource, ModuleSource}; 7use hir::{DefWithBody, HasSource, ModuleSource};
7use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; 8use ra_db::{FileId, SourceDatabase, SourceDatabaseExt};
8use ra_prof::profile; 9use ra_prof::profile;
9use ra_syntax::{AstNode, TextRange}; 10use ra_syntax::{AstNode, TextRange};
10use rustc_hash::FxHashSet; 11use rustc_hash::FxHashMap;
11 12
12use crate::db::RootDatabase; 13use crate::db::RootDatabase;
13 14
14use super::{NameDefinition, NameKind}; 15use super::{NameDefinition, NameKind};
15 16
17pub struct SearchScope {
18 entries: FxHashMap<FileId, Option<TextRange>>,
19}
20
21impl SearchScope {
22 fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope {
23 SearchScope { entries }
24 }
25 pub fn single_file(file: FileId) -> SearchScope {
26 SearchScope::new(std::iter::once((file, None)).collect())
27 }
28 pub(crate) fn intersection(&self, other: &SearchScope) -> SearchScope {
29 let (mut small, mut large) = (&self.entries, &other.entries);
30 if small.len() > large.len() {
31 mem::swap(&mut small, &mut large)
32 }
33
34 let res = small
35 .iter()
36 .filter_map(|(file_id, r1)| {
37 let r2 = large.get(file_id)?;
38 let r = intersect_ranges(*r1, *r2)?;
39 Some((*file_id, r))
40 })
41 .collect();
42 return SearchScope::new(res);
43
44 fn intersect_ranges(
45 r1: Option<TextRange>,
46 r2: Option<TextRange>,
47 ) -> Option<Option<TextRange>> {
48 match (r1, r2) {
49 (None, r) | (r, None) => Some(r),
50 (Some(r1), Some(r2)) => {
51 let r = r1.intersection(&r2)?;
52 Some(Some(r))
53 }
54 }
55 }
56 }
57}
58
59impl IntoIterator for SearchScope {
60 type Item = (FileId, Option<TextRange>);
61 type IntoIter = std::collections::hash_map::IntoIter<FileId, Option<TextRange>>;
62 fn into_iter(self) -> Self::IntoIter {
63 self.entries.into_iter()
64 }
65}
66
16impl NameDefinition { 67impl NameDefinition {
17 pub(crate) fn search_scope(&self, db: &RootDatabase) -> FxHashSet<(FileId, Option<TextRange>)> { 68 pub(crate) fn search_scope(&self, db: &RootDatabase) -> SearchScope {
18 let _p = profile("search_scope"); 69 let _p = profile("search_scope");
19 70
20 let module_src = self.container.definition_source(db); 71 let module_src = self.container.definition_source(db);
21 let file_id = module_src.file_id.original_file(db); 72 let file_id = module_src.file_id.original_file(db);
22 73
23 if let NameKind::Pat((def, _)) = self.kind { 74 if let NameKind::Pat((def, _)) = self.kind {
24 let mut res = FxHashSet::default(); 75 let mut res = FxHashMap::default();
25 let range = match def { 76 let range = match def {
26 DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), 77 DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(),
27 DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), 78 DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(),
28 DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), 79 DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(),
29 }; 80 };
30 res.insert((file_id, Some(range))); 81 res.insert(file_id, Some(range));
31 return res; 82 return SearchScope::new(res);
32 } 83 }
33 84
34 let vis = 85 let vis =
@@ -36,37 +87,37 @@ impl NameDefinition {
36 87
37 if vis.as_str() == "pub(super)" { 88 if vis.as_str() == "pub(super)" {
38 if let Some(parent_module) = self.container.parent(db) { 89 if let Some(parent_module) = self.container.parent(db) {
39 let mut files = FxHashSet::default(); 90 let mut res = FxHashMap::default();
40 let parent_src = parent_module.definition_source(db); 91 let parent_src = parent_module.definition_source(db);
41 let file_id = parent_src.file_id.original_file(db); 92 let file_id = parent_src.file_id.original_file(db);
42 93
43 match parent_src.ast { 94 match parent_src.ast {
44 ModuleSource::Module(m) => { 95 ModuleSource::Module(m) => {
45 let range = Some(m.syntax().text_range()); 96 let range = Some(m.syntax().text_range());
46 files.insert((file_id, range)); 97 res.insert(file_id, range);
47 } 98 }
48 ModuleSource::SourceFile(_) => { 99 ModuleSource::SourceFile(_) => {
49 files.insert((file_id, None)); 100 res.insert(file_id, None);
50 files.extend(parent_module.children(db).map(|m| { 101 res.extend(parent_module.children(db).map(|m| {
51 let src = m.definition_source(db); 102 let src = m.definition_source(db);
52 (src.file_id.original_file(db), None) 103 (src.file_id.original_file(db), None)
53 })); 104 }));
54 } 105 }
55 } 106 }
56 return files; 107 return SearchScope::new(res);
57 } 108 }
58 } 109 }
59 110
60 if vis.as_str() != "" { 111 if vis.as_str() != "" {
61 let source_root_id = db.file_source_root(file_id); 112 let source_root_id = db.file_source_root(file_id);
62 let source_root = db.source_root(source_root_id); 113 let source_root = db.source_root(source_root_id);
63 let mut files = 114 let mut res =
64 source_root.walk().map(|id| (id.into(), None)).collect::<FxHashSet<_>>(); 115 source_root.walk().map(|id| (id.into(), None)).collect::<FxHashMap<_, _>>();
65 116
66 // FIXME: add "pub(in path)" 117 // FIXME: add "pub(in path)"
67 118
68 if vis.as_str() == "pub(crate)" { 119 if vis.as_str() == "pub(crate)" {
69 return files; 120 return SearchScope::new(res);
70 } 121 }
71 if vis.as_str() == "pub" { 122 if vis.as_str() == "pub" {
72 let krate = self.container.krate(db).unwrap(); 123 let krate = self.container.krate(db).unwrap();
@@ -77,19 +128,19 @@ impl NameDefinition {
77 let root_file = crate_graph.crate_root(crate_id); 128 let root_file = crate_graph.crate_root(crate_id);
78 let source_root_id = db.file_source_root(root_file); 129 let source_root_id = db.file_source_root(root_file);
79 let source_root = db.source_root(source_root_id); 130 let source_root = db.source_root(source_root_id);
80 files.extend(source_root.walk().map(|id| (id.into(), None))); 131 res.extend(source_root.walk().map(|id| (id.into(), None)));
81 } 132 }
82 } 133 }
83 return files; 134 return SearchScope::new(res);
84 } 135 }
85 } 136 }
86 137
87 let mut res = FxHashSet::default(); 138 let mut res = FxHashMap::default();
88 let range = match module_src.ast { 139 let range = match module_src.ast {
89 ModuleSource::Module(m) => Some(m.syntax().text_range()), 140 ModuleSource::Module(m) => Some(m.syntax().text_range()),
90 ModuleSource::SourceFile(_) => None, 141 ModuleSource::SourceFile(_) => None,
91 }; 142 };
92 res.insert((file_id, range)); 143 res.insert(file_id, range);
93 res 144 SearchScope::new(res)
94 } 145 }
95} 146}