diff options
author | Aleksey Kladov <[email protected]> | 2020-08-19 23:54:44 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-08-19 23:54:44 +0100 |
commit | e262149b7cb56ccf86cc5e17a75d0ca809ecab0e (patch) | |
tree | 68d56a0998d9cf703b2f2cf0ef6cf2db51b7ad08 /crates/ide_db | |
parent | 5dafd39ad4396c7feb10720e33924d39e8ef2e66 (diff) |
Optimize reference search
Diffstat (limited to 'crates/ide_db')
-rw-r--r-- | crates/ide_db/src/search.rs | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index fa0830b23..edab1d644 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -203,11 +203,25 @@ impl<'a> FindUsages<'a> { | |||
203 | } | 203 | } |
204 | 204 | ||
205 | pub fn at_least_one(self) -> bool { | 205 | pub fn at_least_one(self) -> bool { |
206 | !self.all().is_empty() | 206 | let mut found = false; |
207 | self.search(&mut |_reference| { | ||
208 | found = true; | ||
209 | true | ||
210 | }); | ||
211 | found | ||
207 | } | 212 | } |
208 | 213 | ||
209 | pub fn all(self) -> Vec<Reference> { | 214 | pub fn all(self) -> Vec<Reference> { |
210 | let _p = profile::span("Definition::find_usages"); | 215 | let mut res = Vec::new(); |
216 | self.search(&mut |reference| { | ||
217 | res.push(reference); | ||
218 | false | ||
219 | }); | ||
220 | res | ||
221 | } | ||
222 | |||
223 | fn search(self, sink: &mut dyn FnMut(Reference) -> bool) { | ||
224 | let _p = profile::span("FindUsages:search"); | ||
211 | let sema = self.sema; | 225 | let sema = self.sema; |
212 | 226 | ||
213 | let search_scope = { | 227 | let search_scope = { |
@@ -219,13 +233,11 @@ impl<'a> FindUsages<'a> { | |||
219 | }; | 233 | }; |
220 | 234 | ||
221 | let name = match self.def.name(sema.db) { | 235 | let name = match self.def.name(sema.db) { |
222 | None => return Vec::new(), | ||
223 | Some(it) => it.to_string(), | 236 | Some(it) => it.to_string(), |
237 | None => return, | ||
224 | }; | 238 | }; |
225 | 239 | ||
226 | let pat = name.as_str(); | 240 | let pat = name.as_str(); |
227 | let mut refs = vec![]; | ||
228 | |||
229 | for (file_id, search_range) in search_scope { | 241 | for (file_id, search_range) in search_scope { |
230 | let text = sema.db.file_text(file_id); | 242 | let text = sema.db.file_text(file_id); |
231 | let search_range = | 243 | let search_range = |
@@ -240,10 +252,9 @@ impl<'a> FindUsages<'a> { | |||
240 | } | 252 | } |
241 | 253 | ||
242 | let name_ref: ast::NameRef = | 254 | let name_ref: ast::NameRef = |
243 | if let Some(name_ref) = sema.find_node_at_offset_with_descend(&tree, offset) { | 255 | match sema.find_node_at_offset_with_descend(&tree, offset) { |
244 | name_ref | 256 | Some(it) => it, |
245 | } else { | 257 | None => continue, |
246 | continue; | ||
247 | }; | 258 | }; |
248 | 259 | ||
249 | match classify_name_ref(&sema, &name_ref) { | 260 | match classify_name_ref(&sema, &name_ref) { |
@@ -256,43 +267,45 @@ impl<'a> FindUsages<'a> { | |||
256 | ReferenceKind::Other | 267 | ReferenceKind::Other |
257 | }; | 268 | }; |
258 | 269 | ||
259 | let file_range = sema.original_range(name_ref.syntax()); | 270 | let reference = Reference { |
260 | refs.push(Reference { | 271 | file_range: sema.original_range(name_ref.syntax()), |
261 | file_range, | ||
262 | kind, | 272 | kind, |
263 | access: reference_access(&def, &name_ref), | 273 | access: reference_access(&def, &name_ref), |
264 | }); | 274 | }; |
275 | if sink(reference) { | ||
276 | return; | ||
277 | } | ||
265 | } | 278 | } |
266 | Some(NameRefClass::FieldShorthand { local, field }) => { | 279 | Some(NameRefClass::FieldShorthand { local, field }) => { |
267 | match self.def { | 280 | let reference = match self.def { |
268 | Definition::Field(_) if &field == self.def => refs.push(Reference { | 281 | Definition::Field(_) if &field == self.def => Reference { |
269 | file_range: self.sema.original_range(name_ref.syntax()), | 282 | file_range: self.sema.original_range(name_ref.syntax()), |
270 | kind: ReferenceKind::FieldShorthandForField, | 283 | kind: ReferenceKind::FieldShorthandForField, |
271 | access: reference_access(&field, &name_ref), | 284 | access: reference_access(&field, &name_ref), |
272 | }), | 285 | }, |
273 | Definition::Local(l) if &local == l => refs.push(Reference { | 286 | Definition::Local(l) if &local == l => Reference { |
274 | file_range: self.sema.original_range(name_ref.syntax()), | 287 | file_range: self.sema.original_range(name_ref.syntax()), |
275 | kind: ReferenceKind::FieldShorthandForLocal, | 288 | kind: ReferenceKind::FieldShorthandForLocal, |
276 | access: reference_access(&Definition::Local(local), &name_ref), | 289 | access: reference_access(&Definition::Local(local), &name_ref), |
277 | }), | 290 | }, |
278 | 291 | _ => continue, // not a usage | |
279 | _ => {} // not a usage | ||
280 | }; | 292 | }; |
293 | if sink(reference) { | ||
294 | return; | ||
295 | } | ||
281 | } | 296 | } |
282 | _ => {} // not a usage | 297 | _ => {} // not a usage |
283 | } | 298 | } |
284 | } | 299 | } |
285 | } | 300 | } |
286 | refs | ||
287 | } | 301 | } |
288 | } | 302 | } |
289 | 303 | ||
290 | fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { | 304 | fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { |
291 | // Only Locals and Fields have accesses for now. | 305 | // Only Locals and Fields have accesses for now. |
292 | match def { | 306 | if !matches!(def, Definition::Local(_) | Definition::Field(_)) { |
293 | Definition::Local(_) | Definition::Field(_) => {} | 307 | return None; |
294 | _ => return None, | 308 | } |
295 | }; | ||
296 | 309 | ||
297 | let mode = name_ref.syntax().ancestors().find_map(|node| { | 310 | let mode = name_ref.syntax().ancestors().find_map(|node| { |
298 | match_ast! { | 311 | match_ast! { |