|
7 | 7 | use std::{convert::TryInto, mem};
|
8 | 8 |
|
9 | 9 | use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
|
10 |
| -use hir::{DefWithBody, HasSource, Module, ModuleSource, Semantics, Visibility}; |
| 10 | +use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; |
11 | 11 | use once_cell::unsync::Lazy;
|
12 | 12 | use rustc_hash::FxHashMap;
|
13 | 13 | use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
|
@@ -78,6 +78,76 @@ impl SearchScope {
|
78 | 78 | SearchScope { entries }
|
79 | 79 | }
|
80 | 80 |
|
| 81 | + fn crate_graph(db: &RootDatabase) -> SearchScope { |
| 82 | + let mut entries = FxHashMap::default(); |
| 83 | + |
| 84 | + let graph = db.crate_graph(); |
| 85 | + for krate in graph.iter() { |
| 86 | + let root_file = graph[krate].root_file_id; |
| 87 | + let source_root_id = db.file_source_root(root_file); |
| 88 | + let source_root = db.source_root(source_root_id); |
| 89 | + entries.extend(source_root.iter().map(|id| (id, None))); |
| 90 | + } |
| 91 | + SearchScope { entries } |
| 92 | + } |
| 93 | + |
| 94 | + fn reverse_dependencies(db: &RootDatabase, of: hir::Crate) -> SearchScope { |
| 95 | + let mut entries = FxHashMap::default(); |
| 96 | + for rev_dep in of.transitive_reverse_dependencies(db) { |
| 97 | + let root_file = rev_dep.root_file(db); |
| 98 | + let source_root_id = db.file_source_root(root_file); |
| 99 | + let source_root = db.source_root(source_root_id); |
| 100 | + entries.extend(source_root.iter().map(|id| (id, None))); |
| 101 | + } |
| 102 | + SearchScope { entries } |
| 103 | + } |
| 104 | + |
| 105 | + fn krate(db: &RootDatabase, of: hir::Crate) -> SearchScope { |
| 106 | + let root_file = of.root_file(db); |
| 107 | + let source_root_id = db.file_source_root(root_file); |
| 108 | + let source_root = db.source_root(source_root_id); |
| 109 | + SearchScope { |
| 110 | + entries: source_root.iter().map(|id| (id, None)).collect::<FxHashMap<_, _>>(), |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + fn module(db: &RootDatabase, module: hir::Module) -> SearchScope { |
| 115 | + let mut entries = FxHashMap::default(); |
| 116 | + |
| 117 | + let mut to_visit = vec![module]; |
| 118 | + let mut is_first = true; |
| 119 | + while let Some(module) = to_visit.pop() { |
| 120 | + let src = module.definition_source(db); |
| 121 | + let file_id = src.file_id.original_file(db); |
| 122 | + match src.value { |
| 123 | + ModuleSource::Module(m) => { |
| 124 | + if is_first { |
| 125 | + let range = Some(m.syntax().text_range()); |
| 126 | + entries.insert(file_id, range); |
| 127 | + } else { |
| 128 | + // We have already added the enclosing file to the search scope, |
| 129 | + // so do nothing. |
| 130 | + } |
| 131 | + } |
| 132 | + ModuleSource::BlockExpr(b) => { |
| 133 | + if is_first { |
| 134 | + let range = Some(b.syntax().text_range()); |
| 135 | + entries.insert(file_id, range); |
| 136 | + } else { |
| 137 | + // We have already added the enclosing file to the search scope, |
| 138 | + // so do nothing. |
| 139 | + } |
| 140 | + } |
| 141 | + ModuleSource::SourceFile(_) => { |
| 142 | + entries.insert(file_id, None); |
| 143 | + } |
| 144 | + }; |
| 145 | + is_first = false; |
| 146 | + to_visit.extend(module.children(db)); |
| 147 | + } |
| 148 | + SearchScope { entries } |
| 149 | + } |
| 150 | + |
81 | 151 | pub fn empty() -> SearchScope {
|
82 | 152 | SearchScope::new(FxHashMap::default())
|
83 | 153 | }
|
@@ -140,34 +210,26 @@ impl Definition {
|
140 | 210 | let _p = profile::span("search_scope");
|
141 | 211 |
|
142 | 212 | if let Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) = self {
|
143 |
| - let mut res = FxHashMap::default(); |
144 |
| - |
145 |
| - let graph = db.crate_graph(); |
146 |
| - for krate in graph.iter() { |
147 |
| - let root_file = graph[krate].root_file_id; |
148 |
| - let source_root_id = db.file_source_root(root_file); |
149 |
| - let source_root = db.source_root(source_root_id); |
150 |
| - res.extend(source_root.iter().map(|id| (id, None))); |
151 |
| - } |
152 |
| - return SearchScope::new(res); |
| 213 | + return SearchScope::crate_graph(db); |
153 | 214 | }
|
154 | 215 |
|
155 | 216 | let module = match self.module(db) {
|
156 | 217 | Some(it) => it,
|
157 | 218 | None => return SearchScope::empty(),
|
158 | 219 | };
|
159 |
| - let module_src = module.definition_source(db); |
160 |
| - let file_id = module_src.file_id.original_file(db); |
| 220 | + let InFile { file_id, value: module_source } = module.definition_source(db); |
| 221 | + let file_id = file_id.original_file(db); |
161 | 222 |
|
162 | 223 | if let Definition::Local(var) = self {
|
163 | 224 | let range = match var.parent(db) {
|
164 | 225 | DefWithBody::Function(f) => f.source(db).map(|src| src.value.syntax().text_range()),
|
165 | 226 | DefWithBody::Const(c) => c.source(db).map(|src| src.value.syntax().text_range()),
|
166 | 227 | DefWithBody::Static(s) => s.source(db).map(|src| src.value.syntax().text_range()),
|
167 | 228 | };
|
168 |
| - let mut res = FxHashMap::default(); |
169 |
| - res.insert(file_id, range); |
170 |
| - return SearchScope::new(res); |
| 229 | + return match range { |
| 230 | + Some(range) => SearchScope::file_range(FileRange { file_id, range }), |
| 231 | + None => SearchScope::single_file(file_id), |
| 232 | + }; |
171 | 233 | }
|
172 | 234 |
|
173 | 235 | if let Definition::GenericParam(hir::GenericParam::LifetimeParam(param)) = self {
|
@@ -198,73 +260,39 @@ impl Definition {
|
198 | 260 | it.source(db).map(|src| src.value.syntax().text_range())
|
199 | 261 | }
|
200 | 262 | };
|
201 |
| - let mut res = FxHashMap::default(); |
202 |
| - res.insert(file_id, range); |
203 |
| - return SearchScope::new(res); |
| 263 | + return match range { |
| 264 | + Some(range) => SearchScope::file_range(FileRange { file_id, range }), |
| 265 | + None => SearchScope::single_file(file_id), |
| 266 | + }; |
204 | 267 | }
|
205 | 268 |
|
206 |
| - let vis = self.visibility(db); |
207 |
| - |
208 |
| - if let Some(Visibility::Module(module)) = vis.and_then(|it| it.into()) { |
209 |
| - let module: Module = module.into(); |
210 |
| - let mut res = FxHashMap::default(); |
211 |
| - |
212 |
| - let mut to_visit = vec![module]; |
213 |
| - let mut is_first = true; |
214 |
| - while let Some(module) = to_visit.pop() { |
215 |
| - let src = module.definition_source(db); |
216 |
| - let file_id = src.file_id.original_file(db); |
217 |
| - match src.value { |
218 |
| - ModuleSource::Module(m) => { |
219 |
| - if is_first { |
220 |
| - let range = Some(m.syntax().text_range()); |
221 |
| - res.insert(file_id, range); |
222 |
| - } else { |
223 |
| - // We have already added the enclosing file to the search scope, |
224 |
| - // so do nothing. |
225 |
| - } |
226 |
| - } |
227 |
| - ModuleSource::BlockExpr(b) => { |
228 |
| - if is_first { |
229 |
| - let range = Some(b.syntax().text_range()); |
230 |
| - res.insert(file_id, range); |
231 |
| - } else { |
232 |
| - // We have already added the enclosing file to the search scope, |
233 |
| - // so do nothing. |
234 |
| - } |
235 |
| - } |
236 |
| - ModuleSource::SourceFile(_) => { |
237 |
| - res.insert(file_id, None); |
238 |
| - } |
| 269 | + if let Definition::Macro(macro_def) = self { |
| 270 | + if macro_def.kind() == hir::MacroKind::Declarative { |
| 271 | + return if macro_def.attrs(db).by_key("macro_export").exists() { |
| 272 | + SearchScope::reverse_dependencies(db, module.krate()) |
| 273 | + } else { |
| 274 | + SearchScope::krate(db, module.krate()) |
239 | 275 | };
|
240 |
| - is_first = false; |
241 |
| - to_visit.extend(module.children(db)); |
242 | 276 | }
|
243 |
| - |
244 |
| - return SearchScope::new(res); |
245 | 277 | }
|
246 | 278 |
|
| 279 | + let vis = self.visibility(db); |
247 | 280 | if let Some(Visibility::Public) = vis {
|
248 |
| - let mut res = FxHashMap::default(); |
249 |
| - |
250 |
| - let krate = module.krate(); |
251 |
| - for rev_dep in krate.transitive_reverse_dependencies(db) { |
252 |
| - let root_file = rev_dep.root_file(db); |
253 |
| - let source_root_id = db.file_source_root(root_file); |
254 |
| - let source_root = db.source_root(source_root_id); |
255 |
| - res.extend(source_root.iter().map(|id| (id, None))); |
256 |
| - } |
257 |
| - return SearchScope::new(res); |
| 281 | + return SearchScope::reverse_dependencies(db, module.krate()); |
| 282 | + } |
| 283 | + if let Some(Visibility::Module(module)) = vis { |
| 284 | + return SearchScope::module(db, module.into()); |
258 | 285 | }
|
259 | 286 |
|
260 |
| - let mut res = FxHashMap::default(); |
261 |
| - let range = match module_src.value { |
| 287 | + let range = match module_source { |
262 | 288 | ModuleSource::Module(m) => Some(m.syntax().text_range()),
|
263 | 289 | ModuleSource::BlockExpr(b) => Some(b.syntax().text_range()),
|
264 | 290 | ModuleSource::SourceFile(_) => None,
|
265 | 291 | };
|
266 |
| - res.insert(file_id, range); |
267 |
| - SearchScope::new(res) |
| 292 | + match range { |
| 293 | + Some(range) => SearchScope::file_range(FileRange { file_id, range }), |
| 294 | + None => SearchScope::single_file(file_id), |
| 295 | + } |
268 | 296 | }
|
269 | 297 |
|
270 | 298 | pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> {
|
|
0 commit comments