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(-) (limited to 'crates/ide_db/src') 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 From 8d4be829e09dae4af7b4a82b379fdb8700b0929f Mon Sep 17 00:00:00 2001 From: unexge Date: Sun, 4 Apr 2021 00:04:31 +0300 Subject: Add convert tuple struct to named struct assist --- crates/ide_db/src/search.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'crates/ide_db/src') diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 02f5e514b..90e4e7b03 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs @@ -430,6 +430,15 @@ impl<'a> FindUsages<'a> { sink: &mut dyn FnMut(FileId, FileReference) -> bool, ) -> bool { match NameRefClass::classify(self.sema, &name_ref) { + Some(NameRefClass::Definition(def)) if &def == 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: reference_access(&def, &name_ref), + }; + sink(file_id, reference) + } Some(NameRefClass::Definition(Definition::SelfType(impl_))) => { let ty = impl_.self_ty(self.sema.db); @@ -448,15 +457,6 @@ impl<'a> FindUsages<'a> { false } - Some(NameRefClass::Definition(def)) if &def == 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: reference_access(&def, &name_ref), - }; - sink(file_id, reference) - } Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); let reference = match self.def { -- cgit v1.2.3 From 322cd1fa7fb870f44860bc42ef3b894e5a42bb70 Mon Sep 17 00:00:00 2001 From: unexge Date: Wed, 21 Apr 2021 16:42:47 +0300 Subject: Use multiple loops instead of `Iterator::chain` in `FindUsages` --- crates/ide_db/src/search.rs | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'crates/ide_db/src') diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 90e4e7b03..8f899ea56 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs @@ -4,10 +4,9 @@ //! get a super-set of matches. Then, we we confirm each match using precise //! name resolution. -use std::{convert::TryInto, iter, mem}; +use std::{convert::TryInto, mem}; use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; -use either::Either; use hir::{ DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, Visibility, }; @@ -370,37 +369,47 @@ impl<'a> FindUsages<'a> { let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); - 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 mut handle_match = |idx: usize| -> bool { let offset: TextSize = idx.try_into().unwrap(); if !search_range.contains_inclusive(offset) { - continue; + return false; } if let Some(name) = sema.find_node_at_offset_with_descend(&tree, offset) { match name { ast::NameLike::NameRef(name_ref) => { if self.found_name_ref(&name_ref, sink) { - return; + return true; } } ast::NameLike::Name(name) => { if self.found_name(&name, sink) { - return; + return true; } } ast::NameLike::Lifetime(lifetime) => { if self.found_lifetime(&lifetime, sink) { - return; + return true; } } } } + + return false; + }; + + for (idx, _) in text.match_indices(pat) { + if handle_match(idx) { + return; + } + } + + if search_for_self { + for (idx, _) in text.match_indices("Self") { + if handle_match(idx) { + return; + } + } } } } -- cgit v1.2.3