diff options
Diffstat (limited to 'crates/ide/src/references.rs')
-rw-r--r-- | crates/ide/src/references.rs | 98 |
1 files changed, 52 insertions, 46 deletions
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index b774a2be1..132680bfb 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs | |||
@@ -14,8 +14,7 @@ pub(crate) mod rename; | |||
14 | use hir::Semantics; | 14 | use hir::Semantics; |
15 | use ide_db::{ | 15 | use ide_db::{ |
16 | defs::{Definition, NameClass, NameRefClass}, | 16 | defs::{Definition, NameClass, NameRefClass}, |
17 | search::Reference, | 17 | search::{FileReference, FileReferences, ReferenceAccess, ReferenceKind, SearchScope}, |
18 | search::{ReferenceAccess, ReferenceKind, SearchScope}, | ||
19 | RootDatabase, | 18 | RootDatabase, |
20 | }; | 19 | }; |
21 | use syntax::{ | 20 | use syntax::{ |
@@ -29,7 +28,7 @@ use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeI | |||
29 | #[derive(Debug, Clone)] | 28 | #[derive(Debug, Clone)] |
30 | pub struct ReferenceSearchResult { | 29 | pub struct ReferenceSearchResult { |
31 | declaration: Declaration, | 30 | declaration: Declaration, |
32 | references: Vec<Reference>, | 31 | references: Vec<FileReferences>, |
33 | } | 32 | } |
34 | 33 | ||
35 | #[derive(Debug, Clone)] | 34 | #[derive(Debug, Clone)] |
@@ -48,7 +47,7 @@ impl ReferenceSearchResult { | |||
48 | &self.declaration.nav | 47 | &self.declaration.nav |
49 | } | 48 | } |
50 | 49 | ||
51 | pub fn references(&self) -> &[Reference] { | 50 | pub fn references(&self) -> &[FileReferences] { |
52 | &self.references | 51 | &self.references |
53 | } | 52 | } |
54 | 53 | ||
@@ -63,20 +62,22 @@ impl ReferenceSearchResult { | |||
63 | // allow turning ReferenceSearchResult into an iterator | 62 | // allow turning ReferenceSearchResult into an iterator |
64 | // over References | 63 | // over References |
65 | impl IntoIterator for ReferenceSearchResult { | 64 | impl IntoIterator for ReferenceSearchResult { |
66 | type Item = Reference; | 65 | type Item = FileReferences; |
67 | type IntoIter = std::vec::IntoIter<Reference>; | 66 | type IntoIter = std::vec::IntoIter<FileReferences>; |
68 | 67 | ||
69 | fn into_iter(mut self) -> Self::IntoIter { | 68 | fn into_iter(mut self) -> Self::IntoIter { |
70 | let mut v = Vec::with_capacity(self.len()); | 69 | let mut v = Vec::with_capacity(self.len()); |
71 | v.push(Reference { | 70 | v.append(&mut self.references); |
72 | file_range: FileRange { | 71 | let decl_ref = FileReference { |
73 | file_id: self.declaration.nav.file_id, | 72 | range: self.declaration.nav.focus_or_full_range(), |
74 | range: self.declaration.nav.focus_or_full_range(), | ||
75 | }, | ||
76 | kind: self.declaration.kind, | 73 | kind: self.declaration.kind, |
77 | access: self.declaration.access, | 74 | access: self.declaration.access, |
78 | }); | 75 | }; |
79 | v.append(&mut self.references); | 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 | } | ||
80 | v.into_iter() | 81 | v.into_iter() |
81 | } | 82 | } |
82 | } | 83 | } |
@@ -109,13 +110,11 @@ 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 references = def.usages(sema).set_scope(search_scope).all(); |
113 | .usages(sema) | 114 | references.iter_mut().for_each(|it| { |
114 | .set_scope(search_scope) | 115 | it.references.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) |
115 | .all() | 116 | }); |
116 | .into_iter() | 117 | references.retain(|r| !r.references.is_empty()); |
117 | .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) | ||
118 | .collect(); | ||
119 | 118 | ||
120 | let nav = def.try_to_nav(sema.db)?; | 119 | let nav = def.try_to_nav(sema.db)?; |
121 | let decl_range = nav.focus_or_full_range(); | 120 | let decl_range = nav.focus_or_full_range(); |
@@ -255,7 +254,8 @@ fn try_find_self_references( | |||
255 | syntax: &SyntaxNode, | 254 | syntax: &SyntaxNode, |
256 | position: FilePosition, | 255 | position: FilePosition, |
257 | ) -> Option<RangeInfo<ReferenceSearchResult>> { | 256 | ) -> Option<RangeInfo<ReferenceSearchResult>> { |
258 | let self_token = syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])?; | 257 | let FilePosition { file_id, offset } = position; |
258 | let self_token = syntax.token_at_offset(offset).find(|t| t.kind() == T![self])?; | ||
259 | let parent = self_token.parent(); | 259 | let parent = self_token.parent(); |
260 | match_ast! { | 260 | match_ast! { |
261 | match parent { | 261 | match parent { |
@@ -276,7 +276,7 @@ fn try_find_self_references( | |||
276 | 276 | ||
277 | let declaration = Declaration { | 277 | let declaration = Declaration { |
278 | nav: NavigationTarget { | 278 | nav: NavigationTarget { |
279 | file_id: position.file_id, | 279 | file_id, |
280 | full_range: self_param.syntax().text_range(), | 280 | full_range: self_param.syntax().text_range(), |
281 | focus_range: Some(param_self_token.text_range()), | 281 | focus_range: Some(param_self_token.text_range()), |
282 | name: param_self_token.text().clone(), | 282 | name: param_self_token.text().clone(), |
@@ -295,25 +295,29 @@ fn try_find_self_references( | |||
295 | let references = function | 295 | let references = function |
296 | .body() | 296 | .body() |
297 | .map(|body| { | 297 | .map(|body| { |
298 | body.syntax() | 298 | FileReferences { |
299 | .descendants() | 299 | file_id, |
300 | .filter_map(ast::PathExpr::cast) | 300 | references: body |
301 | .filter_map(|expr| { | 301 | .syntax() |
302 | let path = expr.path()?; | 302 | .descendants() |
303 | if path.qualifier().is_none() { | 303 | .filter_map(ast::PathExpr::cast) |
304 | path.segment()?.self_token() | 304 | .filter_map(|expr| { |
305 | } else { | 305 | let path = expr.path()?; |
306 | None | 306 | if path.qualifier().is_none() { |
307 | } | 307 | path.segment()?.self_token() |
308 | }) | 308 | } else { |
309 | .map(|token| Reference { | 309 | None |
310 | file_range: FileRange { file_id: position.file_id, range: token.text_range() }, | 310 | } |
311 | kind: ReferenceKind::SelfKw, | 311 | }) |
312 | access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration | 312 | .map(|token| FileReference { |
313 | }) | 313 | range: token.text_range(), |
314 | .collect() | 314 | kind: ReferenceKind::SelfKw, |
315 | access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration | ||
316 | }) | ||
317 | .collect(), | ||
318 | } | ||
315 | }) | 319 | }) |
316 | .unwrap_or_default(); | 320 | .map_or_else(Vec::default, |it| vec![it]); |
317 | 321 | ||
318 | Some(RangeInfo::new( | 322 | Some(RangeInfo::new( |
319 | param_self_token.text_range(), | 323 | param_self_token.text_range(), |
@@ -324,7 +328,7 @@ fn try_find_self_references( | |||
324 | #[cfg(test)] | 328 | #[cfg(test)] |
325 | mod tests { | 329 | mod tests { |
326 | use expect_test::{expect, Expect}; | 330 | use expect_test::{expect, Expect}; |
327 | use ide_db::base_db::FileId; | 331 | use ide_db::{base_db::FileId, search::FileReferences}; |
328 | use stdx::format_to; | 332 | use stdx::format_to; |
329 | 333 | ||
330 | use crate::{fixture, SearchScope}; | 334 | use crate::{fixture, SearchScope}; |
@@ -1018,12 +1022,14 @@ impl Foo { | |||
1018 | actual += "\n\n"; | 1022 | actual += "\n\n"; |
1019 | } | 1023 | } |
1020 | 1024 | ||
1021 | for r in &refs.references { | 1025 | for FileReferences { file_id, references } in refs.references { |
1022 | format_to!(actual, "{:?} {:?} {:?}", r.file_range.file_id, r.file_range.range, r.kind); | 1026 | for r in references { |
1023 | if let Some(access) = r.access { | 1027 | format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind); |
1024 | format_to!(actual, " {:?}", access); | 1028 | if let Some(access) = r.access { |
1029 | format_to!(actual, " {:?}", access); | ||
1030 | } | ||
1031 | actual += "\n"; | ||
1025 | } | 1032 | } |
1026 | actual += "\n"; | ||
1027 | } | 1033 | } |
1028 | expect.assert_eq(&actual) | 1034 | expect.assert_eq(&actual) |
1029 | } | 1035 | } |