aboutsummaryrefslogtreecommitdiff
path: root/crates
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
parentfbdb32adfc49e0d69b7fd8e44135bea59382d2cb (diff)
Ensure uniqueness of file ids in reference search via hashmap
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/handlers/extract_struct_from_enum_variant.rs6
-rw-r--r--crates/assists/src/handlers/inline_local_variable.rs14
-rw-r--r--crates/assists/src/handlers/remove_unused_param.rs18
-rw-r--r--crates/ide/src/call_hierarchy.rs4
-rw-r--r--crates/ide/src/references.rs97
-rw-r--r--crates/ide/src/references/rename.rs20
-rw-r--r--crates/ide_db/src/search.rs48
-rw-r--r--crates/rust-analyzer/src/handlers.rs24
-rw-r--r--crates/ssr/src/search.rs12
9 files changed, 122 insertions, 121 deletions
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
index 21b13977b..e3ef04932 100644
--- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -8,7 +8,7 @@ use ide_db::{
8 insert_use::{insert_use, ImportScope}, 8 insert_use::{insert_use, ImportScope},
9 mod_path_to_ast, 9 mod_path_to_ast,
10 }, 10 },
11 search::{FileReference, FileReferences}, 11 search::FileReference,
12 RootDatabase, 12 RootDatabase,
13}; 13};
14use rustc_hash::FxHashSet; 14use rustc_hash::FxHashSet;
@@ -63,10 +63,10 @@ pub(crate) fn extract_struct_from_enum_variant(
63 let current_module = enum_hir.module(ctx.db()); 63 let current_module = enum_hir.module(ctx.db());
64 visited_modules_set.insert(current_module); 64 visited_modules_set.insert(current_module);
65 let mut def_rewriter = None; 65 let mut def_rewriter = None;
66 for FileReferences { file_id, references: refs } in usages { 66 for (file_id, references) in usages {
67 let mut rewriter = SyntaxRewriter::default(); 67 let mut rewriter = SyntaxRewriter::default();
68 let source_file = ctx.sema.parse(file_id); 68 let source_file = ctx.sema.parse(file_id);
69 for reference in refs { 69 for reference in references {
70 update_reference( 70 update_reference(
71 ctx, 71 ctx,
72 &mut rewriter, 72 &mut rewriter,
diff --git a/crates/assists/src/handlers/inline_local_variable.rs b/crates/assists/src/handlers/inline_local_variable.rs
index 928df6825..dc798daaa 100644
--- a/crates/assists/src/handlers/inline_local_variable.rs
+++ b/crates/assists/src/handlers/inline_local_variable.rs
@@ -47,8 +47,8 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O
47 47
48 let def = ctx.sema.to_def(&bind_pat)?; 48 let def = ctx.sema.to_def(&bind_pat)?;
49 let def = Definition::Local(def); 49 let def = Definition::Local(def);
50 let refs = def.usages(&ctx.sema).all(); 50 let usages = def.usages(&ctx.sema).all();
51 if refs.is_empty() { 51 if usages.is_empty() {
52 mark::hit!(test_not_applicable_if_variable_unused); 52 mark::hit!(test_not_applicable_if_variable_unused);
53 return None; 53 return None;
54 }; 54 };
@@ -66,9 +66,10 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O
66 let_stmt.syntax().text_range() 66 let_stmt.syntax().text_range()
67 }; 67 };
68 68
69 let wrap_in_parens = refs 69 let wrap_in_parens = usages
70 .iter() 70 .references
71 .flat_map(|refs| &refs.references) 71 .values()
72 .flatten()
72 .map(|&FileReference { range, .. }| { 73 .map(|&FileReference { range, .. }| {
73 let usage_node = 74 let usage_node =
74 ctx.covering_node_for_range(range).ancestors().find_map(ast::PathExpr::cast)?; 75 ctx.covering_node_for_range(range).ancestors().find_map(ast::PathExpr::cast)?;
@@ -115,8 +116,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O
115 target, 116 target,
116 move |builder| { 117 move |builder| {
117 builder.delete(delete_range); 118 builder.delete(delete_range);
118 for (reference, should_wrap) in 119 for (reference, should_wrap) in usages.references.values().flatten().zip(wrap_in_parens)
119 refs.iter().flat_map(|refs| &refs.references).zip(wrap_in_parens)
120 { 120 {
121 let replacement = 121 let replacement =
122 if should_wrap { init_in_paren.clone() } else { init_str.clone() }; 122 if should_wrap { init_in_paren.clone() } else { init_str.clone() };
diff --git a/crates/assists/src/handlers/remove_unused_param.rs b/crates/assists/src/handlers/remove_unused_param.rs
index 4f3b8ac46..c961680e2 100644
--- a/crates/assists/src/handlers/remove_unused_param.rs
+++ b/crates/assists/src/handlers/remove_unused_param.rs
@@ -1,7 +1,4 @@
1use ide_db::{ 1use ide_db::{base_db::FileId, defs::Definition, search::FileReference};
2 defs::Definition,
3 search::{FileReference, FileReferences},
4};
5use syntax::{ 2use syntax::{
6 algo::find_node_at_range, 3 algo::find_node_at_range,
7 ast::{self, ArgListOwner}, 4 ast::{self, ArgListOwner},
@@ -61,8 +58,8 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
61 param.syntax().text_range(), 58 param.syntax().text_range(),
62 |builder| { 59 |builder| {
63 builder.delete(range_to_remove(param.syntax())); 60 builder.delete(range_to_remove(param.syntax()));
64 for usages in fn_def.usages(&ctx.sema).all() { 61 for (file_id, references) in fn_def.usages(&ctx.sema).all() {
65 process_usages(ctx, builder, usages, param_position); 62 process_usages(ctx, builder, file_id, references, param_position);
66 } 63 }
67 }, 64 },
68 ) 65 )
@@ -71,12 +68,13 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
71fn process_usages( 68fn process_usages(
72 ctx: &AssistContext, 69 ctx: &AssistContext,
73 builder: &mut AssistBuilder, 70 builder: &mut AssistBuilder,
74 usages: FileReferences, 71 file_id: FileId,
72 references: Vec<FileReference>,
75 arg_to_remove: usize, 73 arg_to_remove: usize,
76) { 74) {
77 let source_file = ctx.sema.parse(usages.file_id); 75 let source_file = ctx.sema.parse(file_id);
78 builder.edit_file(usages.file_id); 76 builder.edit_file(file_id);
79 for usage in usages.references { 77 for usage in references {
80 if let Some(text_range) = process_usage(&source_file, usage, arg_to_remove) { 78 if let Some(text_range) = process_usage(&source_file, usage, arg_to_remove) {
81 builder.delete(text_range); 79 builder.delete(text_range);
82 } 80 }
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index 90d3b9a31..e8999a7f3 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -3,8 +3,8 @@
3use indexmap::IndexMap; 3use indexmap::IndexMap;
4 4
5use hir::Semantics; 5use hir::Semantics;
6use ide_db::call_info::FnCallNode;
6use ide_db::RootDatabase; 7use ide_db::RootDatabase;
7use ide_db::{call_info::FnCallNode, search::FileReferences};
8use syntax::{ast, AstNode, TextRange}; 8use syntax::{ast, AstNode, TextRange};
9 9
10use crate::{ 10use crate::{
@@ -47,7 +47,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio
47 47
48 let mut calls = CallLocations::default(); 48 let mut calls = CallLocations::default();
49 49
50 for &FileReferences { file_id, ref references } in refs.info.references() { 50 for (&file_id, references) in refs.info.references().iter() {
51 let file = sema.parse(file_id); 51 let file = sema.parse(file_id);
52 let file = file.syntax(); 52 let file = file.syntax();
53 for reference in references { 53 for reference in references {
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
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::{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)]
29pub struct ReferenceSearchResult { 30pub 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
64impl IntoIterator for ReferenceSearchResult { 76impl 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
144fn find_name( 145fn 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)]
329mod tests { 328mod 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 {
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index dd08e1c32..5207388b5 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -9,7 +9,7 @@ use hir::{Module, ModuleDef, ModuleSource, Semantics};
9use ide_db::{ 9use ide_db::{
10 base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}, 10 base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt},
11 defs::{Definition, NameClass, NameRefClass}, 11 defs::{Definition, NameClass, NameRefClass},
12 search::FileReferences, 12 search::FileReference,
13 RootDatabase, 13 RootDatabase,
14}; 14};
15use syntax::{ 15use syntax::{
@@ -176,7 +176,8 @@ fn find_all_refs(
176 176
177fn source_edit_from_references( 177fn source_edit_from_references(
178 sema: &Semantics<RootDatabase>, 178 sema: &Semantics<RootDatabase>,
179 &FileReferences { file_id, ref references }: &FileReferences, 179 file_id: FileId,
180 references: &[FileReference],
180 new_name: &str, 181 new_name: &str,
181) -> SourceFileEdit { 182) -> SourceFileEdit {
182 let mut edit = TextEdit::builder(); 183 let mut edit = TextEdit::builder();
@@ -283,10 +284,9 @@ fn rename_mod(
283 } 284 }
284 285
285 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; 286 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
286 let ref_edits = refs 287 let ref_edits = refs.references().iter().map(|(&file_id, references)| {
287 .references() 288 source_edit_from_references(sema, file_id, references, new_name)
288 .iter() 289 });
289 .map(|reference| source_edit_from_references(sema, reference, new_name));
290 source_file_edits.extend(ref_edits); 290 source_file_edits.extend(ref_edits);
291 291
292 Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) 292 Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits)))
@@ -341,7 +341,9 @@ fn rename_to_self(
341 let mut edits = refs 341 let mut edits = refs
342 .references() 342 .references()
343 .iter() 343 .iter()
344 .map(|reference| source_edit_from_references(sema, reference, "self")) 344 .map(|(&file_id, references)| {
345 source_edit_from_references(sema, file_id, references, "self")
346 })
345 .collect::<Vec<_>>(); 347 .collect::<Vec<_>>();
346 348
347 edits.push(SourceFileEdit { 349 edits.push(SourceFileEdit {
@@ -467,7 +469,9 @@ fn rename_reference(
467 469
468 let edit = refs 470 let edit = refs
469 .into_iter() 471 .into_iter()
470 .map(|reference| source_edit_from_references(sema, &reference, new_name)) 472 .map(|(file_id, references)| {
473 source_edit_from_references(sema, file_id, &references, new_name)
474 })
471 .collect::<Vec<_>>(); 475 .collect::<Vec<_>>();
472 476
473 Ok(RangeInfo::new(range, SourceChange::from(edit))) 477 Ok(RangeInfo::new(range, SourceChange::from(edit)))
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
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index d862f370a..2cc57f022 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -12,7 +12,6 @@ use ide::{
12 FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, LineIndex, NavigationTarget, 12 FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, LineIndex, NavigationTarget,
13 Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, SymbolKind, TextEdit, 13 Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, SymbolKind, TextEdit,
14}; 14};
15use ide_db::search::FileReferences;
16use itertools::Itertools; 15use itertools::Itertools;
17use lsp_server::ErrorCode; 16use lsp_server::ErrorCode;
18use lsp_types::{ 17use lsp_types::{
@@ -813,18 +812,14 @@ pub(crate) fn handle_references(
813 }; 812 };
814 813
815 let locations = if params.context.include_declaration { 814 let locations = if params.context.include_declaration {
816 let mut locations = Vec::default(); 815 refs.references_with_declaration()
817 refs.into_iter().for_each(|it| { 816 .file_ranges()
818 locations.extend( 817 .filter_map(|frange| to_proto::location(&snap, frange).ok())
819 it.file_ranges().filter_map(|frange| to_proto::location(&snap, frange).ok()), 818 .collect()
820 )
821 });
822 locations
823 } else { 819 } else {
824 // Only iterate over the references if include_declaration was false 820 // Only iterate over the references if include_declaration was false
825 refs.references() 821 refs.references()
826 .iter() 822 .file_ranges()
827 .flat_map(FileReferences::file_ranges)
828 .filter_map(|frange| to_proto::location(&snap, frange).ok()) 823 .filter_map(|frange| to_proto::location(&snap, frange).ok())
829 .collect() 824 .collect()
830 }; 825 };
@@ -1181,8 +1176,7 @@ pub(crate) fn handle_code_lens_resolve(
1181 .unwrap_or(None) 1176 .unwrap_or(None)
1182 .map(|r| { 1177 .map(|r| {
1183 r.references() 1178 r.references()
1184 .iter() 1179 .file_ranges()
1185 .flat_map(FileReferences::file_ranges)
1186 .filter_map(|frange| to_proto::location(&snap, frange).ok()) 1180 .filter_map(|frange| to_proto::location(&snap, frange).ok())
1187 .collect_vec() 1181 .collect_vec()
1188 }) 1182 })
@@ -1227,11 +1221,11 @@ pub(crate) fn handle_document_highlight(
1227 }; 1221 };
1228 1222
1229 let res = refs 1223 let res = refs
1230 .into_iter() 1224 .references_with_declaration()
1231 .find(|refs| refs.file_id == position.file_id) 1225 .references
1226 .get(&position.file_id)
1232 .map(|file_refs| { 1227 .map(|file_refs| {
1233 file_refs 1228 file_refs
1234 .references
1235 .into_iter() 1229 .into_iter()
1236 .map(|r| DocumentHighlight { 1230 .map(|r| DocumentHighlight {
1237 range: to_proto::range(&line_index, r.range), 1231 range: to_proto::range(&line_index, r.range),
diff --git a/crates/ssr/src/search.rs b/crates/ssr/src/search.rs
index a1d653aff..a3eb2e800 100644
--- a/crates/ssr/src/search.rs
+++ b/crates/ssr/src/search.rs
@@ -20,7 +20,7 @@ use test_utils::mark;
20/// them more than once. 20/// them more than once.
21#[derive(Default)] 21#[derive(Default)]
22pub(crate) struct UsageCache { 22pub(crate) struct UsageCache {
23 usages: Vec<(Definition, Vec<FileReferences>)>, 23 usages: Vec<(Definition, FileReferences)>,
24} 24}
25 25
26impl<'db> MatchFinder<'db> { 26impl<'db> MatchFinder<'db> {
@@ -58,11 +58,7 @@ impl<'db> MatchFinder<'db> {
58 ) { 58 ) {
59 if let Some(resolved_path) = pick_path_for_usages(pattern) { 59 if let Some(resolved_path) = pick_path_for_usages(pattern) {
60 let definition: Definition = resolved_path.resolution.clone().into(); 60 let definition: Definition = resolved_path.resolution.clone().into();
61 for file_range in self 61 for file_range in self.find_usages(usage_cache, definition).file_ranges() {
62 .find_usages(usage_cache, definition)
63 .iter()
64 .flat_map(FileReferences::file_ranges)
65 {
66 if let Some(node_to_match) = self.find_node_to_match(resolved_path, file_range) { 62 if let Some(node_to_match) = self.find_node_to_match(resolved_path, file_range) {
67 if !is_search_permitted_ancestors(&node_to_match) { 63 if !is_search_permitted_ancestors(&node_to_match) {
68 mark::hit!(use_declaration_with_braces); 64 mark::hit!(use_declaration_with_braces);
@@ -112,7 +108,7 @@ impl<'db> MatchFinder<'db> {
112 &self, 108 &self,
113 usage_cache: &'a mut UsageCache, 109 usage_cache: &'a mut UsageCache,
114 definition: Definition, 110 definition: Definition,
115 ) -> &'a [FileReferences] { 111 ) -> &'a FileReferences {
116 // Logically if a lookup succeeds we should just return it. Unfortunately returning it would 112 // Logically if a lookup succeeds we should just return it. Unfortunately returning it would
117 // extend the lifetime of the borrow, then we wouldn't be able to do the insertion on a 113 // extend the lifetime of the borrow, then we wouldn't be able to do the insertion on a
118 // cache miss. This is a limitation of NLL and is fixed with Polonius. For now we do two 114 // cache miss. This is a limitation of NLL and is fixed with Polonius. For now we do two
@@ -254,7 +250,7 @@ fn is_search_permitted(node: &SyntaxNode) -> bool {
254} 250}
255 251
256impl UsageCache { 252impl UsageCache {
257 fn find(&mut self, definition: &Definition) -> Option<&[FileReferences]> { 253 fn find(&mut self, definition: &Definition) -> Option<&FileReferences> {
258 // We expect a very small number of cache entries (generally 1), so a linear scan should be 254 // We expect a very small number of cache entries (generally 1), so a linear scan should be
259 // fast enough and avoids the need to implement Hash for Definition. 255 // fast enough and avoids the need to implement Hash for Definition.
260 for (d, refs) in &self.usages { 256 for (d, refs) in &self.usages {