From d3a112d68c74cbd02630f6c909071c94872c193f Mon Sep 17 00:00:00 2001 From: unexge Date: Sun, 4 Apr 2021 00:01:49 +0300 Subject: Allow including `Self` kw references to `FindUsages` --- crates/ide_db/src/search.rs | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file 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 @@ //! get a super-set of matches. Then, we we confirm each match using precise //! name resolution. -use std::{convert::TryInto, mem}; +use std::{convert::TryInto, iter, mem}; use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; -use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; +use either::Either; +use hir::{ + DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, Visibility, +}; use once_cell::unsync::Lazy; use rustc_hash::FxHashMap; use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; @@ -295,7 +298,7 @@ impl Definition { } pub fn usages<'a>(&'a self, sema: &'a Semantics) -> FindUsages<'a> { - FindUsages { def: self, sema, scope: None } + FindUsages { def: self, sema, scope: None, include_self_kw_refs: false } } } @@ -303,9 +306,15 @@ pub struct FindUsages<'a> { def: &'a Definition, sema: &'a Semantics<'a, RootDatabase>, scope: Option, + include_self_kw_refs: bool, } impl<'a> FindUsages<'a> { + pub fn include_self_kw_refs(mut self, include: bool) -> FindUsages<'a> { + self.include_self_kw_refs = include; + self + } + pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> { self.set_scope(Some(scope)) } @@ -352,6 +361,8 @@ impl<'a> FindUsages<'a> { }; let pat = name.as_str(); + let search_for_self = self.include_self_kw_refs; + for (file_id, search_range) in search_scope { let text = sema.db.file_text(file_id); let search_range = @@ -359,7 +370,13 @@ impl<'a> FindUsages<'a> { let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); - for (idx, _) in text.match_indices(pat) { + let matches = text.match_indices(pat).chain(if search_for_self { + Either::Left(text.match_indices("Self")) + } else { + Either::Right(iter::empty()) + }); + + for (idx, _) in matches { let offset: TextSize = idx.try_into().unwrap(); if !search_range.contains_inclusive(offset) { continue; @@ -413,6 +430,24 @@ impl<'a> FindUsages<'a> { sink: &mut dyn FnMut(FileId, FileReference) -> bool, ) -> bool { match NameRefClass::classify(self.sema, &name_ref) { + Some(NameRefClass::Definition(Definition::SelfType(impl_))) => { + let ty = impl_.self_ty(self.sema.db); + + if let Some(adt) = ty.as_adt() { + if &Definition::ModuleDef(ModuleDef::Adt(adt)) == self.def { + let FileRange { file_id, range } = + self.sema.original_range(name_ref.syntax()); + let reference = FileReference { + range, + name: ast::NameLike::NameRef(name_ref.clone()), + access: None, + }; + return sink(file_id, reference); + } + } + + false + } Some(NameRefClass::Definition(def)) if &def == self.def => { let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); let reference = FileReference { -- cgit v1.2.3