diff options
Diffstat (limited to 'crates/ra_ide_api/src/references')
-rw-r--r-- | crates/ra_ide_api/src/references/rename.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/search_scope.rs | 58 |
2 files changed, 49 insertions, 15 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 1c4fb742f..b6eb248b7 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs | |||
@@ -2,30 +2,63 @@ | |||
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. |
5 | use std::mem; | ||
5 | 6 | ||
6 | use hir::{DefWithBody, HasSource, ModuleSource}; | 7 | use hir::{DefWithBody, HasSource, ModuleSource}; |
7 | use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; | 8 | use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; |
8 | use ra_prof::profile; | 9 | use ra_prof::profile; |
9 | use ra_syntax::{AstNode, TextRange}; | 10 | use ra_syntax::{AstNode, TextRange}; |
10 | use rustc_hash::FxHashSet; | 11 | use rustc_hash::FxHashMap; |
11 | 12 | ||
12 | use crate::db::RootDatabase; | 13 | use crate::db::RootDatabase; |
13 | 14 | ||
14 | use super::{NameDefinition, NameKind}; | 15 | use super::{NameDefinition, NameKind}; |
15 | 16 | ||
16 | pub struct SearchScope { | 17 | pub struct SearchScope { |
17 | entries: FxHashSet<(FileId, Option<TextRange>)>, | 18 | entries: FxHashMap<FileId, Option<TextRange>>, |
18 | } | 19 | } |
19 | 20 | ||
20 | impl SearchScope { | 21 | impl SearchScope { |
21 | fn new(entries: FxHashSet<(FileId, Option<TextRange>)>) -> SearchScope { | 22 | fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope { |
22 | SearchScope { entries } | 23 | SearchScope { entries } |
23 | } | 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 | } | ||
24 | } | 57 | } |
25 | 58 | ||
26 | impl IntoIterator for SearchScope { | 59 | impl IntoIterator for SearchScope { |
27 | type Item = (FileId, Option<TextRange>); | 60 | type Item = (FileId, Option<TextRange>); |
28 | type IntoIter = std::collections::hash_set::IntoIter<Self::Item>; | 61 | type IntoIter = std::collections::hash_map::IntoIter<FileId, Option<TextRange>>; |
29 | fn into_iter(self) -> Self::IntoIter { | 62 | fn into_iter(self) -> Self::IntoIter { |
30 | self.entries.into_iter() | 63 | self.entries.into_iter() |
31 | } | 64 | } |
@@ -39,13 +72,13 @@ impl NameDefinition { | |||
39 | let file_id = module_src.file_id.original_file(db); | 72 | let file_id = module_src.file_id.original_file(db); |
40 | 73 | ||
41 | if let NameKind::Pat((def, _)) = self.kind { | 74 | if let NameKind::Pat((def, _)) = self.kind { |
42 | let mut res = FxHashSet::default(); | 75 | let mut res = FxHashMap::default(); |
43 | let range = match def { | 76 | let range = match def { |
44 | DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), | 77 | DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), |
45 | DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), | 78 | DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), |
46 | DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), | 79 | DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), |
47 | }; | 80 | }; |
48 | res.insert((file_id, Some(range))); | 81 | res.insert(file_id, Some(range)); |
49 | return SearchScope::new(res); | 82 | return SearchScope::new(res); |
50 | } | 83 | } |
51 | 84 | ||
@@ -54,17 +87,17 @@ impl NameDefinition { | |||
54 | 87 | ||
55 | if vis.as_str() == "pub(super)" { | 88 | if vis.as_str() == "pub(super)" { |
56 | if let Some(parent_module) = self.container.parent(db) { | 89 | if let Some(parent_module) = self.container.parent(db) { |
57 | let mut res = FxHashSet::default(); | 90 | let mut res = FxHashMap::default(); |
58 | let parent_src = parent_module.definition_source(db); | 91 | let parent_src = parent_module.definition_source(db); |
59 | let file_id = parent_src.file_id.original_file(db); | 92 | let file_id = parent_src.file_id.original_file(db); |
60 | 93 | ||
61 | match parent_src.ast { | 94 | match parent_src.ast { |
62 | ModuleSource::Module(m) => { | 95 | ModuleSource::Module(m) => { |
63 | let range = Some(m.syntax().text_range()); | 96 | let range = Some(m.syntax().text_range()); |
64 | res.insert((file_id, range)); | 97 | res.insert(file_id, range); |
65 | } | 98 | } |
66 | ModuleSource::SourceFile(_) => { | 99 | ModuleSource::SourceFile(_) => { |
67 | res.insert((file_id, None)); | 100 | res.insert(file_id, None); |
68 | res.extend(parent_module.children(db).map(|m| { | 101 | res.extend(parent_module.children(db).map(|m| { |
69 | let src = m.definition_source(db); | 102 | let src = m.definition_source(db); |
70 | (src.file_id.original_file(db), None) | 103 | (src.file_id.original_file(db), None) |
@@ -78,7 +111,8 @@ impl NameDefinition { | |||
78 | if vis.as_str() != "" { | 111 | if vis.as_str() != "" { |
79 | let source_root_id = db.file_source_root(file_id); | 112 | let source_root_id = db.file_source_root(file_id); |
80 | let source_root = db.source_root(source_root_id); | 113 | let source_root = db.source_root(source_root_id); |
81 | let mut res = source_root.walk().map(|id| (id.into(), None)).collect::<FxHashSet<_>>(); | 114 | let mut res = |
115 | source_root.walk().map(|id| (id.into(), None)).collect::<FxHashMap<_, _>>(); | ||
82 | 116 | ||
83 | // FIXME: add "pub(in path)" | 117 | // FIXME: add "pub(in path)" |
84 | 118 | ||
@@ -101,12 +135,12 @@ impl NameDefinition { | |||
101 | } | 135 | } |
102 | } | 136 | } |
103 | 137 | ||
104 | let mut res = FxHashSet::default(); | 138 | let mut res = FxHashMap::default(); |
105 | let range = match module_src.ast { | 139 | let range = match module_src.ast { |
106 | ModuleSource::Module(m) => Some(m.syntax().text_range()), | 140 | ModuleSource::Module(m) => Some(m.syntax().text_range()), |
107 | ModuleSource::SourceFile(_) => None, | 141 | ModuleSource::SourceFile(_) => None, |
108 | }; | 142 | }; |
109 | res.insert((file_id, range)); | 143 | res.insert(file_id, range); |
110 | SearchScope::new(res) | 144 | SearchScope::new(res) |
111 | } | 145 | } |
112 | } | 146 | } |