diff options
Diffstat (limited to 'crates/ide/src/references.rs')
-rw-r--r-- | crates/ide/src/references.rs | 97 |
1 files changed, 48 insertions, 49 deletions
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 132680bfb..c7943dc95 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -13,6 +13,7 @@ pub(crate) mod rename; | |||
13 | 13 | ||
14 | use hir::Semantics; | 14 | use hir::Semantics; |
15 | use ide_db::{ | 15 | use ide_db::{ |
16 | base_db::FileId, | ||
16 | defs::{Definition, NameClass, NameRefClass}, | 17 | defs::{Definition, NameClass, NameRefClass}, |
17 | search::{FileReference, FileReferences, ReferenceAccess, ReferenceKind, SearchScope}, | 18 | search::{FileReference, FileReferences, ReferenceAccess, ReferenceKind, SearchScope}, |
18 | RootDatabase, | 19 | RootDatabase, |
@@ -28,7 +29,7 @@ use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeI | |||
28 | #[derive(Debug, Clone)] | 29 | #[derive(Debug, Clone)] |
29 | pub struct ReferenceSearchResult { | 30 | pub struct ReferenceSearchResult { |
30 | declaration: Declaration, | 31 | declaration: Declaration, |
31 | references: Vec<FileReferences>, | 32 | references: FileReferences, |
32 | } | 33 | } |
33 | 34 | ||
34 | #[derive(Debug, Clone)] | 35 | #[derive(Debug, Clone)] |
@@ -47,10 +48,21 @@ impl ReferenceSearchResult { | |||
47 | &self.declaration.nav | 48 | &self.declaration.nav |
48 | } | 49 | } |
49 | 50 | ||
50 | pub fn references(&self) -> &[FileReferences] { | 51 | pub fn references(&self) -> &FileReferences { |
51 | &self.references | 52 | &self.references |
52 | } | 53 | } |
53 | 54 | ||
55 | pub fn references_with_declaration(mut self) -> FileReferences { | ||
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 | |||
54 | /// Total number of references | 66 | /// Total number of references |
55 | /// At least 1 since all valid references should | 67 | /// At least 1 since all valid references should |
56 | /// Have a declaration | 68 | /// Have a declaration |
@@ -62,23 +74,11 @@ impl ReferenceSearchResult { | |||
62 | // allow turning ReferenceSearchResult into an iterator | 74 | // allow turning ReferenceSearchResult into an iterator |
63 | // over References | 75 | // over References |
64 | impl IntoIterator for ReferenceSearchResult { | 76 | impl IntoIterator for ReferenceSearchResult { |
65 | type Item = FileReferences; | 77 | type Item = (FileId, Vec<FileReference>); |
66 | type IntoIter = std::vec::IntoIter<FileReferences>; | 78 | type IntoIter = std::collections::hash_map::IntoIter<FileId, Vec<FileReference>>; |
67 | 79 | ||
68 | fn into_iter(mut self) -> Self::IntoIter { | 80 | fn into_iter(self) -> Self::IntoIter { |
69 | let mut v = Vec::with_capacity(self.len()); | 81 | self.references_with_declaration().into_iter() |
70 | v.append(&mut self.references); | ||
71 | let decl_ref = FileReference { | ||
72 | range: self.declaration.nav.focus_or_full_range(), | ||
73 | kind: self.declaration.kind, | ||
74 | access: self.declaration.access, | ||
75 | }; | ||
76 | let file_id = self.declaration.nav.file_id; | ||
77 | match v.iter_mut().find(|it| it.file_id == file_id) { | ||
78 | Some(file_refs) => file_refs.references.push(decl_ref), | ||
79 | None => v.push(FileReferences { file_id, references: vec![decl_ref] }), | ||
80 | } | ||
81 | v.into_iter() | ||
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
@@ -110,11 +110,12 @@ pub(crate) fn find_all_refs( | |||
110 | 110 | ||
111 | 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)?; |
112 | 112 | ||
113 | let mut references = def.usages(sema).set_scope(search_scope).all(); | 113 | let mut usages = def.usages(sema).set_scope(search_scope).all(); |
114 | references.iter_mut().for_each(|it| { | 114 | usages |
115 | it.references.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) | 115 | .references |
116 | }); | 116 | .values_mut() |
117 | references.retain(|r| !r.references.is_empty()); | 117 | .for_each(|it| it.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind)); |
118 | usages.references.retain(|_, it| !it.is_empty()); | ||
118 | 119 | ||
119 | let nav = def.try_to_nav(sema.db)?; | 120 | let nav = def.try_to_nav(sema.db)?; |
120 | let decl_range = nav.focus_or_full_range(); | 121 | let decl_range = nav.focus_or_full_range(); |
@@ -138,7 +139,7 @@ pub(crate) fn find_all_refs( | |||
138 | 139 | ||
139 | 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) }; |
140 | 141 | ||
141 | Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })) | 142 | Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references: usages })) |
142 | } | 143 | } |
143 | 144 | ||
144 | fn find_name( | 145 | fn find_name( |
@@ -292,32 +293,30 @@ 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 | FileReferences { | 299 | body.syntax() |
299 | file_id, | 300 | .descendants() |
300 | references: body | 301 | .filter_map(ast::PathExpr::cast) |
301 | .syntax() | 302 | .filter_map(|expr| { |
302 | .descendants() | 303 | let path = expr.path()?; |
303 | .filter_map(ast::PathExpr::cast) | 304 | if path.qualifier().is_none() { |
304 | .filter_map(|expr| { | 305 | path.segment()?.self_token() |
305 | let path = expr.path()?; | 306 | } else { |
306 | if path.qualifier().is_none() { | 307 | None |
307 | path.segment()?.self_token() | 308 | } |
308 | } else { | 309 | }) |
309 | None | 310 | .map(|token| FileReference { |
310 | } | 311 | range: token.text_range(), |
311 | }) | 312 | kind: ReferenceKind::SelfKw, |
312 | .map(|token| FileReference { | 313 | access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration |
313 | range: token.text_range(), | 314 | }) |
314 | kind: ReferenceKind::SelfKw, | 315 | .collect() |
315 | access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration | ||
316 | }) | ||
317 | .collect(), | ||
318 | } | ||
319 | }) | 316 | }) |
320 | .map_or_else(Vec::default, |it| vec![it]); | 317 | .unwrap_or_default(); |
318 | let mut references = FileReferences::default(); | ||
319 | references.references.insert(file_id, refs); | ||
321 | 320 | ||
322 | Some(RangeInfo::new( | 321 | Some(RangeInfo::new( |
323 | param_self_token.text_range(), | 322 | param_self_token.text_range(), |
@@ -328,7 +327,7 @@ fn try_find_self_references( | |||
328 | #[cfg(test)] | 327 | #[cfg(test)] |
329 | mod tests { | 328 | mod tests { |
330 | use expect_test::{expect, Expect}; | 329 | use expect_test::{expect, Expect}; |
331 | use ide_db::{base_db::FileId, search::FileReferences}; | 330 | use ide_db::base_db::FileId; |
332 | use stdx::format_to; | 331 | use stdx::format_to; |
333 | 332 | ||
334 | use crate::{fixture, SearchScope}; | 333 | use crate::{fixture, SearchScope}; |
@@ -1022,7 +1021,7 @@ impl Foo { | |||
1022 | actual += "\n\n"; | 1021 | actual += "\n\n"; |
1023 | } | 1022 | } |
1024 | 1023 | ||
1025 | for FileReferences { file_id, references } in refs.references { | 1024 | for (file_id, references) in refs.references { |
1026 | for r in references { | 1025 | for r in references { |
1027 | format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind); | 1026 | format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind); |
1028 | if let Some(access) = r.access { | 1027 | if let Some(access) = r.access { |