aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db')
-rw-r--r--crates/ide_db/src/search.rs58
1 files changed, 51 insertions, 7 deletions
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index b55e3851e..8f899ea56 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -7,7 +7,9 @@
7use std::{convert::TryInto, mem}; 7use std::{convert::TryInto, 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 hir::{
11 DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, Visibility,
12};
11use once_cell::unsync::Lazy; 13use once_cell::unsync::Lazy;
12use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
13use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; 15use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
@@ -295,7 +297,7 @@ impl Definition {
295 } 297 }
296 298
297 pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { 299 pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> {
298 FindUsages { def: self, sema, scope: None } 300 FindUsages { def: self, sema, scope: None, include_self_kw_refs: false }
299 } 301 }
300} 302}
301 303
@@ -303,9 +305,15 @@ pub struct FindUsages<'a> {
303 def: &'a Definition, 305 def: &'a Definition,
304 sema: &'a Semantics<'a, RootDatabase>, 306 sema: &'a Semantics<'a, RootDatabase>,
305 scope: Option<SearchScope>, 307 scope: Option<SearchScope>,
308 include_self_kw_refs: bool,
306} 309}
307 310
308impl<'a> FindUsages<'a> { 311impl<'a> FindUsages<'a> {
312 pub fn include_self_kw_refs(mut self, include: bool) -> FindUsages<'a> {
313 self.include_self_kw_refs = include;
314 self
315 }
316
309 pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> { 317 pub fn in_scope(self, scope: SearchScope) -> FindUsages<'a> {
310 self.set_scope(Some(scope)) 318 self.set_scope(Some(scope))
311 } 319 }
@@ -352,6 +360,8 @@ impl<'a> FindUsages<'a> {
352 }; 360 };
353 361
354 let pat = name.as_str(); 362 let pat = name.as_str();
363 let search_for_self = self.include_self_kw_refs;
364
355 for (file_id, search_range) in search_scope { 365 for (file_id, search_range) in search_scope {
356 let text = sema.db.file_text(file_id); 366 let text = sema.db.file_text(file_id);
357 let search_range = 367 let search_range =
@@ -359,31 +369,47 @@ impl<'a> FindUsages<'a> {
359 369
360 let tree = Lazy::new(|| sema.parse(file_id).syntax().clone()); 370 let tree = Lazy::new(|| sema.parse(file_id).syntax().clone());
361 371
362 for (idx, _) in text.match_indices(pat) { 372 let mut handle_match = |idx: usize| -> bool {
363 let offset: TextSize = idx.try_into().unwrap(); 373 let offset: TextSize = idx.try_into().unwrap();
364 if !search_range.contains_inclusive(offset) { 374 if !search_range.contains_inclusive(offset) {
365 continue; 375 return false;
366 } 376 }
367 377
368 if let Some(name) = sema.find_node_at_offset_with_descend(&tree, offset) { 378 if let Some(name) = sema.find_node_at_offset_with_descend(&tree, offset) {
369 match name { 379 match name {
370 ast::NameLike::NameRef(name_ref) => { 380 ast::NameLike::NameRef(name_ref) => {
371 if self.found_name_ref(&name_ref, sink) { 381 if self.found_name_ref(&name_ref, sink) {
372 return; 382 return true;
373 } 383 }
374 } 384 }
375 ast::NameLike::Name(name) => { 385 ast::NameLike::Name(name) => {
376 if self.found_name(&name, sink) { 386 if self.found_name(&name, sink) {
377 return; 387 return true;
378 } 388 }
379 } 389 }
380 ast::NameLike::Lifetime(lifetime) => { 390 ast::NameLike::Lifetime(lifetime) => {
381 if self.found_lifetime(&lifetime, sink) { 391 if self.found_lifetime(&lifetime, sink) {
382 return; 392 return true;
383 } 393 }
384 } 394 }
385 } 395 }
386 } 396 }
397
398 return false;
399 };
400
401 for (idx, _) in text.match_indices(pat) {
402 if handle_match(idx) {
403 return;
404 }
405 }
406
407 if search_for_self {
408 for (idx, _) in text.match_indices("Self") {
409 if handle_match(idx) {
410 return;
411 }
412 }
387 } 413 }
388 } 414 }
389 } 415 }
@@ -422,6 +448,24 @@ impl<'a> FindUsages<'a> {
422 }; 448 };
423 sink(file_id, reference) 449 sink(file_id, reference)
424 } 450 }
451 Some(NameRefClass::Definition(Definition::SelfType(impl_))) => {
452 let ty = impl_.self_ty(self.sema.db);
453
454 if let Some(adt) = ty.as_adt() {
455 if &Definition::ModuleDef(ModuleDef::Adt(adt)) == self.def {
456 let FileRange { file_id, range } =
457 self.sema.original_range(name_ref.syntax());
458 let reference = FileReference {
459 range,
460 name: ast::NameLike::NameRef(name_ref.clone()),
461 access: None,
462 };
463 return sink(file_id, reference);
464 }
465 }
466
467 false
468 }
425 Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { 469 Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => {
426 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); 470 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
427 let reference = match self.def { 471 let reference = match self.def {