From fbdb32adfc49e0d69b7fd8e44135bea59382d2cb Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 12 Jan 2021 00:05:07 +0100 Subject: Group references by FileId --- crates/ide/src/references.rs | 98 +++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 46 deletions(-) (limited to 'crates/ide/src/references.rs') 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; use hir::Semantics; use ide_db::{ defs::{Definition, NameClass, NameRefClass}, - search::Reference, - search::{ReferenceAccess, ReferenceKind, SearchScope}, + search::{FileReference, FileReferences, ReferenceAccess, ReferenceKind, SearchScope}, RootDatabase, }; use syntax::{ @@ -29,7 +28,7 @@ use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeI #[derive(Debug, Clone)] pub struct ReferenceSearchResult { declaration: Declaration, - references: Vec, + references: Vec, } #[derive(Debug, Clone)] @@ -48,7 +47,7 @@ impl ReferenceSearchResult { &self.declaration.nav } - pub fn references(&self) -> &[Reference] { + pub fn references(&self) -> &[FileReferences] { &self.references } @@ -63,20 +62,22 @@ impl ReferenceSearchResult { // allow turning ReferenceSearchResult into an iterator // over References impl IntoIterator for ReferenceSearchResult { - type Item = Reference; - type IntoIter = std::vec::IntoIter; + type Item = FileReferences; + type IntoIter = std::vec::IntoIter; fn into_iter(mut self) -> Self::IntoIter { let mut v = Vec::with_capacity(self.len()); - v.push(Reference { - file_range: FileRange { - file_id: self.declaration.nav.file_id, - range: self.declaration.nav.focus_or_full_range(), - }, + v.append(&mut self.references); + let decl_ref = FileReference { + range: self.declaration.nav.focus_or_full_range(), kind: self.declaration.kind, access: self.declaration.access, - }); - v.append(&mut self.references); + }; + let file_id = self.declaration.nav.file_id; + match v.iter_mut().find(|it| it.file_id == file_id) { + Some(file_refs) => file_refs.references.push(decl_ref), + None => v.push(FileReferences { file_id, references: vec![decl_ref] }), + } v.into_iter() } } @@ -109,13 +110,11 @@ pub(crate) fn find_all_refs( let RangeInfo { range, info: def } = find_name(&sema, &syntax, position, opt_name)?; - let references = def - .usages(sema) - .set_scope(search_scope) - .all() - .into_iter() - .filter(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) - .collect(); + let mut references = def.usages(sema).set_scope(search_scope).all(); + references.iter_mut().for_each(|it| { + it.references.retain(|r| search_kind == ReferenceKind::Other || search_kind == r.kind) + }); + references.retain(|r| !r.references.is_empty()); let nav = def.try_to_nav(sema.db)?; let decl_range = nav.focus_or_full_range(); @@ -255,7 +254,8 @@ fn try_find_self_references( syntax: &SyntaxNode, position: FilePosition, ) -> Option> { - let self_token = syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])?; + let FilePosition { file_id, offset } = position; + let self_token = syntax.token_at_offset(offset).find(|t| t.kind() == T![self])?; let parent = self_token.parent(); match_ast! { match parent { @@ -276,7 +276,7 @@ fn try_find_self_references( let declaration = Declaration { nav: NavigationTarget { - file_id: position.file_id, + file_id, full_range: self_param.syntax().text_range(), focus_range: Some(param_self_token.text_range()), name: param_self_token.text().clone(), @@ -295,25 +295,29 @@ fn try_find_self_references( let references = function .body() .map(|body| { - body.syntax() - .descendants() - .filter_map(ast::PathExpr::cast) - .filter_map(|expr| { - let path = expr.path()?; - if path.qualifier().is_none() { - path.segment()?.self_token() - } else { - None - } - }) - .map(|token| Reference { - file_range: FileRange { file_id: position.file_id, range: token.text_range() }, - kind: ReferenceKind::SelfKw, - access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration - }) - .collect() + FileReferences { + file_id, + references: body + .syntax() + .descendants() + .filter_map(ast::PathExpr::cast) + .filter_map(|expr| { + let path = expr.path()?; + if path.qualifier().is_none() { + path.segment()?.self_token() + } else { + None + } + }) + .map(|token| FileReference { + range: token.text_range(), + kind: ReferenceKind::SelfKw, + access: declaration.access, // FIXME: properly check access kind here instead of copying it from the declaration + }) + .collect(), + } }) - .unwrap_or_default(); + .map_or_else(Vec::default, |it| vec![it]); Some(RangeInfo::new( param_self_token.text_range(), @@ -324,7 +328,7 @@ fn try_find_self_references( #[cfg(test)] mod tests { use expect_test::{expect, Expect}; - use ide_db::base_db::FileId; + use ide_db::{base_db::FileId, search::FileReferences}; use stdx::format_to; use crate::{fixture, SearchScope}; @@ -1018,12 +1022,14 @@ impl Foo { actual += "\n\n"; } - for r in &refs.references { - format_to!(actual, "{:?} {:?} {:?}", r.file_range.file_id, r.file_range.range, r.kind); - if let Some(access) = r.access { - format_to!(actual, " {:?}", access); + for FileReferences { file_id, references } in refs.references { + for r in references { + format_to!(actual, "{:?} {:?} {:?}", file_id, r.range, r.kind); + if let Some(access) = r.access { + format_to!(actual, " {:?}", access); + } + actual += "\n"; } - actual += "\n"; } expect.assert_eq(&actual) } -- cgit v1.2.3