aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/references.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/references.rs')
-rw-r--r--crates/ide/src/references.rs79
1 files changed, 42 insertions, 37 deletions
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index b774a2be1..7d4757e02 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -13,9 +13,9 @@ pub(crate) mod rename;
13 13
14use hir::Semantics; 14use hir::Semantics;
15use ide_db::{ 15use ide_db::{
16 base_db::FileId,
16 defs::{Definition, NameClass, NameRefClass}, 17 defs::{Definition, NameClass, NameRefClass},
17 search::Reference, 18 search::{FileReference, ReferenceAccess, ReferenceKind, SearchScope, UsageSearchResult},
18 search::{ReferenceAccess, ReferenceKind, SearchScope},
19 RootDatabase, 19 RootDatabase,
20}; 20};
21use syntax::{ 21use syntax::{
@@ -29,7 +29,7 @@ use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeI
29#[derive(Debug, Clone)] 29#[derive(Debug, Clone)]
30pub struct ReferenceSearchResult { 30pub struct ReferenceSearchResult {
31 declaration: Declaration, 31 declaration: Declaration,
32 references: Vec<Reference>, 32 references: UsageSearchResult,
33} 33}
34 34
35#[derive(Debug, Clone)] 35#[derive(Debug, Clone)]
@@ -48,10 +48,21 @@ impl ReferenceSearchResult {
48 &self.declaration.nav 48 &self.declaration.nav
49 } 49 }
50 50
51 pub fn references(&self) -> &[Reference] { 51 pub fn references(&self) -> &UsageSearchResult {
52 &self.references 52 &self.references
53 } 53 }
54 54
55 pub fn references_with_declaration(mut self) -> UsageSearchResult {
56 let decl_ref = FileReference {
57 range: self.declaration.nav.focus_or_full_range(),
58 kind: self.declaration.kind,
59 access: self.declaration.access,
60 };
61 let file_id = self.declaration.nav.file_id;
62 self.references.references.entry(file_id).or_default().push(decl_ref);
63 self.references
64 }
65
55 /// Total number of references 66 /// Total number of references
56 /// At least 1 since all valid references should 67 /// At least 1 since all valid references should
57 /// Have a declaration 68 /// Have a declaration
@@ -63,21 +74,11 @@ impl ReferenceSearchResult {
63// allow turning ReferenceSearchResult into an iterator 74// allow turning ReferenceSearchResult into an iterator
64// over References 75// over References
65impl IntoIterator for ReferenceSearchResult { 76impl IntoIterator for ReferenceSearchResult {
66 type Item = Reference; 77 type Item = (FileId, Vec<FileReference>);
67 type IntoIter = std::vec::IntoIter<Reference>; 78 type IntoIter = std::collections::hash_map::IntoIter<FileId, Vec<FileReference>>;
68 79
69 fn into_iter(mut self) -> Self::IntoIter { 80 fn into_iter(self) -> Self::IntoIter {
70 let mut v = Vec::with_capacity(self.len()); 81 self.references_with_declaration().into_iter()
71 v.push(Reference {
72 file_range: FileRange {
73 file_id: self.declaration.nav.file_id,
74 range: self.declaration.nav.focus_or_full_range(),
75 },
76 kind: self.declaration.kind,
77 access: self.declaration.access,
78 });
79 v.append(&mut self.references);
80 v.into_iter()
81 } 82 }
82} 83}
83 84
@@ -109,13 +110,12 @@ pub(crate) fn find_all_refs(
109 110
110 let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; 111 let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?;
111 112
112 let references = def 113 let mut usages = def.usages(sema).set_scope(search_scope).all();
113 .usages(sema) 114 usages
114 .set_scope(search_scope) 115 .references
115 .all() 116 .values_mut()
116 .into_iter() 117 .for_each(|it| it.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind));
117 .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) 118 usages.references.retain(|_, it| !it.is_empty());
118 .collect();
119 119
120 let nav = def.try_to_nav(sema.db)?; 120 let nav = def.try_to_nav(sema.db)?;
121 let decl_range = nav.focus_or_full_range(); 121 let decl_range = nav.focus_or_full_range();
@@ -139,7 +139,7 @@ pub(crate) fn find_all_refs(
139 139
140 let declaration = Declaration { nav, kind, access: decl_access(&def, &syntax, decl_range) }; 140 let declaration = Declaration { nav, kind, access: decl_access(&def, &syntax, decl_range) };
141 141
142 Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })) 142 Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references: usages }))
143} 143}
144 144
145fn find_name( 145fn find_name(
@@ -255,7 +255,8 @@ fn try_find_self_references(
255 syntax: &SyntaxNode, 255 syntax: &SyntaxNode,
256 position: FilePosition, 256 position: FilePosition,
257) -> Option<RangeInfo<ReferenceSearchResult>> { 257) -> Option<RangeInfo<ReferenceSearchResult>> {
258 let self_token = syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])?; 258 let FilePosition { file_id, offset } = position;
259 let self_token = syntax.token_at_offset(offset).find(|t| t.kind() == T![self])?;
259 let parent = self_token.parent(); 260 let parent = self_token.parent();
260 match_ast! { 261 match_ast! {
261 match parent { 262 match parent {
@@ -276,7 +277,7 @@ fn try_find_self_references(
276 277
277 let declaration = Declaration { 278 let declaration = Declaration {
278 nav: NavigationTarget { 279 nav: NavigationTarget {
279 file_id: position.file_id, 280 file_id,
280 full_range: self_param.syntax().text_range(), 281 full_range: self_param.syntax().text_range(),
281 focus_range: Some(param_self_token.text_range()), 282 focus_range: Some(param_self_token.text_range()),
282 name: param_self_token.text().clone(), 283 name: param_self_token.text().clone(),
@@ -292,7 +293,7 @@ fn try_find_self_references(
292 ReferenceAccess::Read 293 ReferenceAccess::Read
293 }), 294 }),
294 }; 295 };
295 let references = function 296 let refs = function
296 .body() 297 .body()
297 .map(|body| { 298 .map(|body| {
298 body.syntax() 299 body.syntax()
@@ -306,14 +307,16 @@ fn try_find_self_references(
306 None 307 None
307 } 308 }
308 }) 309 })
309 .map(|token| Reference { 310 .map(|token| FileReference {
310 file_range: FileRange { file_id: position.file_id, range: token.text_range() }, 311 range: token.text_range(),
311 kind: ReferenceKind::SelfKw, 312 kind: ReferenceKind::SelfKw,
312 access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration 313 access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration
313 }) 314 })
314 .collect() 315 .collect()
315 }) 316 })
316 .unwrap_or_default(); 317 .unwrap_or_default();
318 let mut references = UsageSearchResult::default();
319 references.references.insert(file_id, refs);
317 320
318 Some(RangeInfo::new( 321 Some(RangeInfo::new(
319 param_self_token.text_range(), 322 param_self_token.text_range(),
@@ -1018,12 +1021,14 @@ impl Foo {
1018 actual += "\n\n"; 1021 actual += "\n\n";
1019 } 1022 }
1020 1023
1021 for r in &refs.references { 1024 for (file_id, references) in refs.references {
1022 format_to!(actual, "{:?} {:?} {:?}", r.file_range.file_id, r.file_range.range, r.kind); 1025 for r in references {
1023 if let Some(access) = r.access { 1026 format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind);
1024 format_to!(actual, " {:?}", access); 1027 if let Some(access) = r.access {
1028 format_to!(actual, " {:?}", access);
1029 }
1030 actual += "\n";
1025 } 1031 }
1026 actual += "\n";
1027 } 1032 }
1028 expect.assert_eq(&actual) 1033 expect.assert_eq(&actual)
1029 } 1034 }