diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/references.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/references/search_scope.rs | 144 |
2 files changed, 1 insertions, 145 deletions
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 95468d434..6fd46c52d 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -31,7 +31,7 @@ use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeI | |||
31 | 31 | ||
32 | pub(crate) use self::rename::rename; | 32 | pub(crate) use self::rename::rename; |
33 | 33 | ||
34 | pub use self::search_scope::SearchScope; | 34 | pub use ra_ide_db::search::SearchScope; |
35 | 35 | ||
36 | #[derive(Debug, Clone)] | 36 | #[derive(Debug, Clone)] |
37 | pub struct ReferenceSearchResult { | 37 | pub struct ReferenceSearchResult { |
diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs index d98c84d91..8b1378917 100644 --- a/crates/ra_ide/src/references/search_scope.rs +++ b/crates/ra_ide/src/references/search_scope.rs | |||
@@ -1,145 +1 @@ | |||
1 | //! Generally, `search_scope` returns files that might contain references for the element. | ||
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`, | ||
4 | //! e.g. for things like local variables. | ||
5 | use std::mem; | ||
6 | |||
7 | use hir::{DefWithBody, HasSource, ModuleSource}; | ||
8 | use ra_db::{FileId, SourceDatabaseExt}; | ||
9 | use ra_prof::profile; | ||
10 | use ra_syntax::{AstNode, TextRange}; | ||
11 | use rustc_hash::FxHashMap; | ||
12 | |||
13 | use ra_ide_db::RootDatabase; | ||
14 | |||
15 | use super::Definition; | ||
16 | |||
17 | pub struct SearchScope { | ||
18 | entries: FxHashMap<FileId, Option<TextRange>>, | ||
19 | } | ||
20 | |||
21 | impl SearchScope { | ||
22 | fn empty() -> SearchScope { | ||
23 | SearchScope { entries: FxHashMap::default() } | ||
24 | } | ||
25 | |||
26 | pub(crate) fn for_def(def: &Definition, db: &RootDatabase) -> SearchScope { | ||
27 | let _p = profile("search_scope"); | ||
28 | let module = match def.module(db) { | ||
29 | Some(it) => it, | ||
30 | None => return SearchScope::empty(), | ||
31 | }; | ||
32 | let module_src = module.definition_source(db); | ||
33 | let file_id = module_src.file_id.original_file(db); | ||
34 | |||
35 | if let Definition::Local(var) = def { | ||
36 | let range = match var.parent(db) { | ||
37 | DefWithBody::Function(f) => f.source(db).value.syntax().text_range(), | ||
38 | DefWithBody::Const(c) => c.source(db).value.syntax().text_range(), | ||
39 | DefWithBody::Static(s) => s.source(db).value.syntax().text_range(), | ||
40 | }; | ||
41 | let mut res = FxHashMap::default(); | ||
42 | res.insert(file_id, Some(range)); | ||
43 | return SearchScope::new(res); | ||
44 | } | ||
45 | |||
46 | let vis = def.visibility(db).as_ref().map(|v| v.syntax().to_string()).unwrap_or_default(); | ||
47 | |||
48 | if vis.as_str() == "pub(super)" { | ||
49 | if let Some(parent_module) = module.parent(db) { | ||
50 | let mut res = FxHashMap::default(); | ||
51 | let parent_src = parent_module.definition_source(db); | ||
52 | let file_id = parent_src.file_id.original_file(db); | ||
53 | |||
54 | match parent_src.value { | ||
55 | ModuleSource::Module(m) => { | ||
56 | let range = Some(m.syntax().text_range()); | ||
57 | res.insert(file_id, range); | ||
58 | } | ||
59 | ModuleSource::SourceFile(_) => { | ||
60 | res.insert(file_id, None); | ||
61 | res.extend(parent_module.children(db).map(|m| { | ||
62 | let src = m.definition_source(db); | ||
63 | (src.file_id.original_file(db), None) | ||
64 | })); | ||
65 | } | ||
66 | } | ||
67 | return SearchScope::new(res); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | if vis.as_str() != "" { | ||
72 | let source_root_id = db.file_source_root(file_id); | ||
73 | let source_root = db.source_root(source_root_id); | ||
74 | let mut res = source_root.walk().map(|id| (id, None)).collect::<FxHashMap<_, _>>(); | ||
75 | |||
76 | // FIXME: add "pub(in path)" | ||
77 | |||
78 | if vis.as_str() == "pub(crate)" { | ||
79 | return SearchScope::new(res); | ||
80 | } | ||
81 | if vis.as_str() == "pub" { | ||
82 | let krate = module.krate(); | ||
83 | for rev_dep in krate.reverse_dependencies(db) { | ||
84 | let root_file = rev_dep.root_file(db); | ||
85 | let source_root_id = db.file_source_root(root_file); | ||
86 | let source_root = db.source_root(source_root_id); | ||
87 | res.extend(source_root.walk().map(|id| (id, None))); | ||
88 | } | ||
89 | return SearchScope::new(res); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | let mut res = FxHashMap::default(); | ||
94 | let range = match module_src.value { | ||
95 | ModuleSource::Module(m) => Some(m.syntax().text_range()), | ||
96 | ModuleSource::SourceFile(_) => None, | ||
97 | }; | ||
98 | res.insert(file_id, range); | ||
99 | SearchScope::new(res) | ||
100 | } | ||
101 | |||
102 | fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope { | ||
103 | SearchScope { entries } | ||
104 | } | ||
105 | pub fn single_file(file: FileId) -> SearchScope { | ||
106 | SearchScope::new(std::iter::once((file, None)).collect()) | ||
107 | } | ||
108 | pub(crate) fn intersection(&self, other: &SearchScope) -> SearchScope { | ||
109 | let (mut small, mut large) = (&self.entries, &other.entries); | ||
110 | if small.len() > large.len() { | ||
111 | mem::swap(&mut small, &mut large) | ||
112 | } | ||
113 | |||
114 | let res = small | ||
115 | .iter() | ||
116 | .filter_map(|(file_id, r1)| { | ||
117 | let r2 = large.get(file_id)?; | ||
118 | let r = intersect_ranges(*r1, *r2)?; | ||
119 | Some((*file_id, r)) | ||
120 | }) | ||
121 | .collect(); | ||
122 | return SearchScope::new(res); | ||
123 | |||
124 | fn intersect_ranges( | ||
125 | r1: Option<TextRange>, | ||
126 | r2: Option<TextRange>, | ||
127 | ) -> Option<Option<TextRange>> { | ||
128 | match (r1, r2) { | ||
129 | (None, r) | (r, None) => Some(r), | ||
130 | (Some(r1), Some(r2)) => { | ||
131 | let r = r1.intersection(&r2)?; | ||
132 | Some(Some(r)) | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | impl IntoIterator for SearchScope { | ||
140 | type Item = (FileId, Option<TextRange>); | ||
141 | type IntoIter = std::collections::hash_map::IntoIter<FileId, Option<TextRange>>; | ||
142 | fn into_iter(self) -> Self::IntoIter { | ||
143 | self.entries.into_iter() | ||
144 | } | ||
145 | } | ||