diff options
Diffstat (limited to 'crates/ide_db/src/search.rs')
-rw-r--r-- | crates/ide_db/src/search.rs | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 67840602b..a840e06a6 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -8,7 +8,8 @@ use std::{convert::TryInto, mem}; | |||
8 | 8 | ||
9 | use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; | 9 | use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; |
10 | use hir::{ | 10 | use hir::{ |
11 | DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, Visibility, | 11 | AsAssocItem, DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, |
12 | Visibility, | ||
12 | }; | 13 | }; |
13 | use once_cell::unsync::Lazy; | 14 | use once_cell::unsync::Lazy; |
14 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
@@ -303,13 +304,13 @@ impl Definition { | |||
303 | } | 304 | } |
304 | } | 305 | } |
305 | 306 | ||
306 | pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { | 307 | pub fn usages<'a>(self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { |
307 | FindUsages { def: self, sema, scope: None, include_self_kw_refs: None } | 308 | FindUsages { def: self, sema, scope: None, include_self_kw_refs: None } |
308 | } | 309 | } |
309 | } | 310 | } |
310 | 311 | ||
311 | pub struct FindUsages<'a> { | 312 | pub struct FindUsages<'a> { |
312 | def: &'a Definition, | 313 | def: Definition, |
313 | sema: &'a Semantics<'a, RootDatabase>, | 314 | sema: &'a Semantics<'a, RootDatabase>, |
314 | scope: Option<SearchScope>, | 315 | scope: Option<SearchScope>, |
315 | include_self_kw_refs: Option<hir::Type>, | 316 | include_self_kw_refs: Option<hir::Type>, |
@@ -318,7 +319,7 @@ pub struct FindUsages<'a> { | |||
318 | impl<'a> FindUsages<'a> { | 319 | impl<'a> FindUsages<'a> { |
319 | /// Enable searching for `Self` when the definition is a type. | 320 | /// Enable searching for `Self` when the definition is a type. |
320 | pub fn include_self_refs(mut self) -> FindUsages<'a> { | 321 | pub fn include_self_refs(mut self) -> FindUsages<'a> { |
321 | self.include_self_kw_refs = def_to_ty(self.sema, self.def); | 322 | self.include_self_kw_refs = def_to_ty(self.sema, &self.def); |
322 | self | 323 | self |
323 | } | 324 | } |
324 | 325 | ||
@@ -408,7 +409,7 @@ impl<'a> FindUsages<'a> { | |||
408 | if let Some(ast::NameLike::NameRef(name_ref)) = | 409 | if let Some(ast::NameLike::NameRef(name_ref)) = |
409 | sema.find_node_at_offset_with_descend(&tree, offset) | 410 | sema.find_node_at_offset_with_descend(&tree, offset) |
410 | { | 411 | { |
411 | if self.found_self_ty_name_ref(&self_ty, &name_ref, sink) { | 412 | if self.found_self_ty_name_ref(self_ty, &name_ref, sink) { |
412 | return; | 413 | return; |
413 | } | 414 | } |
414 | } | 415 | } |
@@ -423,7 +424,7 @@ impl<'a> FindUsages<'a> { | |||
423 | name_ref: &ast::NameRef, | 424 | name_ref: &ast::NameRef, |
424 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, | 425 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, |
425 | ) -> bool { | 426 | ) -> bool { |
426 | match NameRefClass::classify(self.sema, &name_ref) { | 427 | match NameRefClass::classify(self.sema, name_ref) { |
427 | Some(NameRefClass::Definition(Definition::SelfType(impl_))) | 428 | Some(NameRefClass::Definition(Definition::SelfType(impl_))) |
428 | if impl_.self_ty(self.sema.db) == *self_ty => | 429 | if impl_.self_ty(self.sema.db) == *self_ty => |
429 | { | 430 | { |
@@ -445,7 +446,7 @@ impl<'a> FindUsages<'a> { | |||
445 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, | 446 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, |
446 | ) -> bool { | 447 | ) -> bool { |
447 | match NameRefClass::classify_lifetime(self.sema, lifetime) { | 448 | match NameRefClass::classify_lifetime(self.sema, lifetime) { |
448 | Some(NameRefClass::Definition(def)) if &def == self.def => { | 449 | Some(NameRefClass::Definition(def)) if def == self.def => { |
449 | let FileRange { file_id, range } = self.sema.original_range(lifetime.syntax()); | 450 | let FileRange { file_id, range } = self.sema.original_range(lifetime.syntax()); |
450 | let reference = FileReference { | 451 | let reference = FileReference { |
451 | range, | 452 | range, |
@@ -463,13 +464,13 @@ impl<'a> FindUsages<'a> { | |||
463 | name_ref: &ast::NameRef, | 464 | name_ref: &ast::NameRef, |
464 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, | 465 | sink: &mut dyn FnMut(FileId, FileReference) -> bool, |
465 | ) -> bool { | 466 | ) -> bool { |
466 | match NameRefClass::classify(self.sema, &name_ref) { | 467 | match NameRefClass::classify(self.sema, name_ref) { |
467 | Some(NameRefClass::Definition(def)) if &def == self.def => { | 468 | Some(NameRefClass::Definition(def)) if def == self.def => { |
468 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); | 469 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); |
469 | let reference = FileReference { | 470 | let reference = FileReference { |
470 | range, | 471 | range, |
471 | name: ast::NameLike::NameRef(name_ref.clone()), | 472 | name: ast::NameLike::NameRef(name_ref.clone()), |
472 | access: reference_access(&def, &name_ref), | 473 | access: reference_access(&def, name_ref), |
473 | }; | 474 | }; |
474 | sink(file_id, reference) | 475 | sink(file_id, reference) |
475 | } | 476 | } |
@@ -479,7 +480,7 @@ impl<'a> FindUsages<'a> { | |||
479 | let reference = FileReference { | 480 | let reference = FileReference { |
480 | range, | 481 | range, |
481 | name: ast::NameLike::NameRef(name_ref.clone()), | 482 | name: ast::NameLike::NameRef(name_ref.clone()), |
482 | access: reference_access(&def, &name_ref), | 483 | access: reference_access(&def, name_ref), |
483 | }; | 484 | }; |
484 | sink(file_id, reference) | 485 | sink(file_id, reference) |
485 | } else { | 486 | } else { |
@@ -489,11 +490,9 @@ impl<'a> FindUsages<'a> { | |||
489 | Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { | 490 | Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { |
490 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); | 491 | let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); |
491 | let access = match self.def { | 492 | let access = match self.def { |
492 | Definition::Field(_) if &field == self.def => { | 493 | Definition::Field(_) if field == self.def => reference_access(&field, name_ref), |
493 | reference_access(&field, &name_ref) | 494 | Definition::Local(l) if local == l => { |
494 | } | 495 | reference_access(&Definition::Local(local), name_ref) |
495 | Definition::Local(l) if &local == l => { | ||
496 | reference_access(&Definition::Local(local), &name_ref) | ||
497 | } | 496 | } |
498 | _ => return false, | 497 | _ => return false, |
499 | }; | 498 | }; |
@@ -513,7 +512,7 @@ impl<'a> FindUsages<'a> { | |||
513 | match NameClass::classify(self.sema, name) { | 512 | match NameClass::classify(self.sema, name) { |
514 | Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) | 513 | Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) |
515 | if matches!( | 514 | if matches!( |
516 | self.def, Definition::Field(_) if &field_ref == self.def | 515 | self.def, Definition::Field(_) if field_ref == self.def |
517 | ) => | 516 | ) => |
518 | { | 517 | { |
519 | let FileRange { file_id, range } = self.sema.original_range(name.syntax()); | 518 | let FileRange { file_id, range } = self.sema.original_range(name.syntax()); |
@@ -525,12 +524,38 @@ impl<'a> FindUsages<'a> { | |||
525 | }; | 524 | }; |
526 | sink(file_id, reference) | 525 | sink(file_id, reference) |
527 | } | 526 | } |
528 | Some(NameClass::ConstReference(def)) if *self.def == def => { | 527 | Some(NameClass::ConstReference(def)) if self.def == def => { |
529 | let FileRange { file_id, range } = self.sema.original_range(name.syntax()); | 528 | let FileRange { file_id, range } = self.sema.original_range(name.syntax()); |
530 | let reference = | 529 | let reference = |
531 | FileReference { range, name: ast::NameLike::Name(name.clone()), access: None }; | 530 | FileReference { range, name: ast::NameLike::Name(name.clone()), access: None }; |
532 | sink(file_id, reference) | 531 | sink(file_id, reference) |
533 | } | 532 | } |
533 | // Resolve trait impl function definitions to the trait definition's version if self.def is the trait definition's | ||
534 | Some(NameClass::Definition(Definition::ModuleDef(mod_def))) => { | ||
535 | /* poor man's try block */ | ||
536 | (|| { | ||
537 | let this = match self.def { | ||
538 | Definition::ModuleDef(this) if this != mod_def => this, | ||
539 | _ => return None, | ||
540 | }; | ||
541 | let this_trait = this | ||
542 | .as_assoc_item(self.sema.db)? | ||
543 | .containing_trait_or_trait_impl(self.sema.db)?; | ||
544 | let trait_ = mod_def | ||
545 | .as_assoc_item(self.sema.db)? | ||
546 | .containing_trait_or_trait_impl(self.sema.db)?; | ||
547 | (trait_ == this_trait).then(|| { | ||
548 | let FileRange { file_id, range } = self.sema.original_range(name.syntax()); | ||
549 | let reference = FileReference { | ||
550 | range, | ||
551 | name: ast::NameLike::Name(name.clone()), | ||
552 | access: None, | ||
553 | }; | ||
554 | sink(file_id, reference) | ||
555 | }) | ||
556 | })() | ||
557 | .unwrap_or(false) | ||
558 | } | ||
534 | _ => false, | 559 | _ => false, |
535 | } | 560 | } |
536 | } | 561 | } |