aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunexge <[email protected]>2021-04-03 22:01:49 +0100
committerunexge <[email protected]>2021-04-04 18:48:31 +0100
commitd3a112d68c74cbd02630f6c909071c94872c193f (patch)
tree11e69733680a21c3281d9825b867527034a0c5ca
parent0924888cce5f48e0ea0dc7fd8641db92850ef660 (diff)
Allow including `Self` kw references to `FindUsages`
-rw-r--r--crates/ide_db/src/search.rs43
1 files changed, 39 insertions, 4 deletions
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index b55e3851e..02f5e514b 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -4,10 +4,13 @@
4//! get a super-set of matches. Then, we we confirm each match using precise 4//! get a super-set of matches. Then, we we confirm each match using precise
5//! name resolution. 5//! name resolution.
6 6
7use std::{convert::TryInto, mem}; 7use std::{convert::TryInto, iter, mem};
8 8
9use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; 9use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
10use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; 10use either::Either;
11use hir::{
12 DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, Visibility,
13};
11use once_cell::unsync::Lazy; 14use once_cell::unsync::Lazy;
12use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
13use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; 16use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
@@ -295,7 +298,7 @@ impl Definition {
295 } 298 }
296 299
297 pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { 300 pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> {
298 FindUsages { def: self, sema, scope: None } 301 FindUsages { def: self, sema, scope: None, include_self_kw_refs: false }
299 } 302 }
300} 303}
301 304
@@ -303,9 +306,15 @@ pub struct FindUsages<'a> {
303 def: &'a Definition, 306 def: &'a Definition,
304 sema: &'a Semantics<'a, RootDatabase>, 307 sema: &'a Semantics<'a, RootDatabase>,
305 scope: Option<SearchScope>, 308 scope: Option<SearchScope>,
309 include_self_kw_refs: bool,
306} 310}
307 311
308impl<'a> FindUsages<'a> { 312impl<'a> FindUsages<'a> {
313 pub fn include_self_kw_refs(mut self, include: bool) -> FindUsages<'a> {
314 self.include_self_kw_refs = include;
315 self
316 }
317
309 pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> { 318 pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> {
310 self.set_scope(Some(scope)) 319 self.set_scope(Some(scope))
311 } 320 }
@@ -352,6 +361,8 @@ impl<'a> FindUsages<'a> {
352 }; 361 };
353 362
354 let pat = name.as_str(); 363 let pat = name.as_str();
364 let search_for_self = self.include_self_kw_refs;
365
355 for (file_id, search_range) in search_scope { 366 for (file_id, search_range) in search_scope {
356 let text = sema.db.file_text(file_id); 367 let text = sema.db.file_text(file_id);
357 let search_range = 368 let search_range =
@@ -359,7 +370,13 @@ impl<'a> FindUsages<'a> {
359 370
360 let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); 371 let tree = Lazy::new(|| sema.parse(file_id).syntax().clone());
361 372
362 for (idx, _) in text.match_indices(pat) { 373 let matches = text.match_indices(pat).chain(if search_for_self {
374 Either::Left(text.match_indices("Self"))
375 } else {
376 Either::Right(iter::empty())
377 });
378
379 for (idx, _) in matches {
363 let offset: TextSize = idx.try_into().unwrap(); 380 let offset: TextSize = idx.try_into().unwrap();
364 if !search_range.contains_inclusive(offset) { 381 if !search_range.contains_inclusive(offset) {
365 continue; 382 continue;
@@ -413,6 +430,24 @@ impl<'a> FindUsages<'a> {
413 sink: &mut dyn FnMut(FileId, FileReference) -> bool, 430 sink: &mut dyn FnMut(FileId, FileReference) -> bool,
414 ) -> bool { 431 ) -> bool {
415 match NameRefClass::classify(self.sema, &name_ref) { 432 match NameRefClass::classify(self.sema, &name_ref) {
433 Some(NameRefClass::Definition(Definition::SelfType(impl_))) => {
434 let ty = impl_.self_ty(self.sema.db);
435
436 if let Some(adt) = ty.as_adt() {
437 if &Definition::ModuleDef(ModuleDef::Adt(adt)) == self.def {
438 let FileRange { file_id, range } =
439 self.sema.original_range(name_ref.syntax());
440 let reference = FileReference {
441 range,
442 name: ast::NameLike::NameRef(name_ref.clone()),
443 access: None,
444 };
445 return sink(file_id, reference);
446 }
447 }
448
449 false
450 }
416 Some(NameRefClass::Definition(def)) if &def == self.def => { 451 Some(NameRefClass::Definition(def)) if &def == self.def => {
417 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); 452 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
418 let reference = FileReference { 453 let reference = FileReference {