aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-01-12 14:51:02 +0000
committerLukas Wirth <[email protected]>2021-01-12 14:51:02 +0000
commit2c1777a2e264e58fccd5ace94b238c8a497ddbda (patch)
treee7d47c95c6bcdeecd5f321f4ca969d04ca90dff7 /crates/ide_db
parentfbdb32adfc49e0d69b7fd8e44135bea59382d2cb (diff)
Ensure uniqueness of file ids in reference search via hashmap
Diffstat (limited to 'crates/ide_db')
-rw-r--r--crates/ide_db/src/search.rs48
1 files changed, 29 insertions, 19 deletions
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index b8359a9b4..89a313e9b 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -8,7 +8,6 @@ use std::{convert::TryInto, mem};
8 8
9use base_db::{FileId, FileRange, SourceDatabaseExt}; 9use base_db::{FileId, FileRange, SourceDatabaseExt};
10use hir::{DefWithBody, HasSource, Module, ModuleSource, Semantics, Visibility}; 10use hir::{DefWithBody, HasSource, Module, ModuleSource, Semantics, Visibility};
11use itertools::Itertools;
12use once_cell::unsync::Lazy; 11use once_cell::unsync::Lazy;
13use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
14use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; 13use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
@@ -19,17 +18,37 @@ use crate::{
19 RootDatabase, 18 RootDatabase,
20}; 19};
21 20
22#[derive(Debug, Clone)] 21#[derive(Debug, Default, Clone)]
23pub struct FileReferences { 22pub struct FileReferences {
24 pub file_id: FileId, 23 pub references: FxHashMap<FileId, Vec<FileReference>>,
25 pub references: Vec<FileReference>,
26} 24}
27 25
28impl FileReferences { 26impl FileReferences {
27 pub fn is_empty(&self) -> bool {
28 self.references.is_empty()
29 }
30
31 pub fn len(&self) -> usize {
32 self.references.len()
33 }
34
35 pub fn iter(&self) -> impl Iterator<Item = (&FileId, &Vec<FileReference>)> + '_ {
36 self.references.iter()
37 }
38
29 pub fn file_ranges(&self) -> impl Iterator<Item = FileRange> + '_ { 39 pub fn file_ranges(&self) -> impl Iterator<Item = FileRange> + '_ {
30 self.references 40 self.references.iter().flat_map(|(&file_id, refs)| {
31 .iter() 41 refs.iter().map(move |&FileReference { range, .. }| FileRange { file_id, range })
32 .map(move |&FileReference { range, .. }| FileRange { file_id: self.file_id, range }) 42 })
43 }
44}
45
46impl IntoIterator for FileReferences {
47 type Item = (FileId, Vec<FileReference>);
48 type IntoIter = <FxHashMap<FileId, Vec<FileReference>> as IntoIterator>::IntoIter;
49
50 fn into_iter(self) -> Self::IntoIter {
51 self.references.into_iter()
33 } 52 }
34} 53}
35 54
@@ -275,21 +294,12 @@ impl<'a> FindUsages<'a> {
275 } 294 }
276 295
277 /// The [`FileReferences`] returned always have unique [`FileId`]s. 296 /// The [`FileReferences`] returned always have unique [`FileId`]s.
278 pub fn all(self) -> Vec<FileReferences> { 297 pub fn all(self) -> FileReferences {
279 let mut res = <Vec<FileReferences>>::new(); 298 let mut res = FileReferences::default();
280 self.search(&mut |file_id, reference| { 299 self.search(&mut |file_id, reference| {
281 match res.iter_mut().find(|it| it.file_id == file_id) { 300 res.references.entry(file_id).or_default().push(reference);
282 Some(file_refs) => file_refs.references.push(reference),
283 _ => res.push(FileReferences { file_id, references: vec![reference] }),
284 }
285 false 301 false
286 }); 302 });
287 assert!(res
288 .iter()
289 .map(|refs| refs.file_id)
290 .sorted_unstable()
291 .tuple_windows::<(_, _)>()
292 .all(|(a, b)| a < b));
293 res 303 res
294 } 304 }
295 305