aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src/search.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-08-19 23:54:44 +0100
committerAleksey Kladov <[email protected]>2020-08-19 23:54:44 +0100
commite262149b7cb56ccf86cc5e17a75d0ca809ecab0e (patch)
tree68d56a0998d9cf703b2f2cf0ef6cf2db51b7ad08 /crates/ide_db/src/search.rs
parent5dafd39ad4396c7feb10720e33924d39e8ef2e66 (diff)
Optimize reference search
Diffstat (limited to 'crates/ide_db/src/search.rs')
-rw-r--r--crates/ide_db/src/search.rs63
1 files changed, 38 insertions, 25 deletions
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index fa0830b23..edab1d644 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -203,11 +203,25 @@ impl<'a> FindUsages<'a> {
203 } 203 }
204 204
205 pub fn at_least_one(self) -> bool { 205 pub fn at_least_one(self) -> bool {
206 !self.all().is_empty() 206 let mut found = false;
207 self.search(&mut |_reference| {
208 found = true;
209 true
210 });
211 found
207 } 212 }
208 213
209 pub fn all(self) -> Vec<Reference> { 214 pub fn all(self) -> Vec<Reference> {
210 let _p = profile::span("Definition::find_usages"); 215 let mut res = Vec::new();
216 self.search(&mut |reference| {
217 res.push(reference);
218 false
219 });
220 res
221 }
222
223 fn search(self, sink: &mut dyn FnMut(Reference) -> bool) {
224 let _p = profile::span("FindUsages:search");
211 let sema = self.sema; 225 let sema = self.sema;
212 226
213 let search_scope = { 227 let search_scope = {
@@ -219,13 +233,11 @@ impl<'a> FindUsages<'a> {
219 }; 233 };
220 234
221 let name = match self.def.name(sema.db) { 235 let name = match self.def.name(sema.db) {
222 None => return Vec::new(),
223 Some(it) => it.to_string(), 236 Some(it) => it.to_string(),
237 None => return,
224 }; 238 };
225 239
226 let pat = name.as_str(); 240 let pat = name.as_str();
227 let mut refs = vec![];
228
229 for (file_id, search_range) in search_scope { 241 for (file_id, search_range) in search_scope {
230 let text = sema.db.file_text(file_id); 242 let text = sema.db.file_text(file_id);
231 let search_range = 243 let search_range =
@@ -240,10 +252,9 @@ impl<'a> FindUsages<'a> {
240 } 252 }
241 253
242 let name_ref: ast::NameRef = 254 let name_ref: ast::NameRef =
243 if let Some(name_ref) = sema.find_node_at_offset_with_descend(&tree, offset) { 255 match sema.find_node_at_offset_with_descend(&tree, offset) {
244 name_ref 256 Some(it) => it,
245 } else { 257 None => continue,
246 continue;
247 }; 258 };
248 259
249 match classify_name_ref(&sema, &name_ref) { 260 match classify_name_ref(&sema, &name_ref) {
@@ -256,43 +267,45 @@ impl<'a> FindUsages<'a> {
256 ReferenceKind::Other 267 ReferenceKind::Other
257 }; 268 };
258 269
259 let file_range = sema.original_range(name_ref.syntax()); 270 let reference = Reference {
260 refs.push(Reference { 271 file_range: sema.original_range(name_ref.syntax()),
261 file_range,
262 kind, 272 kind,
263 access: reference_access(&def, &name_ref), 273 access: reference_access(&def, &name_ref),
264 }); 274 };
275 if sink(reference) {
276 return;
277 }
265 } 278 }
266 Some(NameRefClass::FieldShorthand { local, field }) => { 279 Some(NameRefClass::FieldShorthand { local, field }) => {
267 match self.def { 280 let reference = match self.def {
268 Definition::Field(_) if &field == self.def => refs.push(Reference { 281 Definition::Field(_) if &field == self.def => Reference {
269 file_range: self.sema.original_range(name_ref.syntax()), 282 file_range: self.sema.original_range(name_ref.syntax()),
270 kind: ReferenceKind::FieldShorthandForField, 283 kind: ReferenceKind::FieldShorthandForField,
271 access: reference_access(&field, &name_ref), 284 access: reference_access(&field, &name_ref),
272 }), 285 },
273 Definition::Local(l) if &local == l => refs.push(Reference { 286 Definition::Local(l) if &local == l => Reference {
274 file_range: self.sema.original_range(name_ref.syntax()), 287 file_range: self.sema.original_range(name_ref.syntax()),
275 kind: ReferenceKind::FieldShorthandForLocal, 288 kind: ReferenceKind::FieldShorthandForLocal,
276 access: reference_access(&Definition::Local(local), &name_ref), 289 access: reference_access(&Definition::Local(local), &name_ref),
277 }), 290 },
278 291 _ => continue, // not a usage
279 _ => {} // not a usage
280 }; 292 };
293 if sink(reference) {
294 return;
295 }
281 } 296 }
282 _ => {} // not a usage 297 _ => {} // not a usage
283 } 298 }
284 } 299 }
285 } 300 }
286 refs
287 } 301 }
288} 302}
289 303
290fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { 304fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {
291 // Only Locals and Fields have accesses for now. 305 // Only Locals and Fields have accesses for now.
292 match def { 306 if !matches!(def, Definition::Local(_) | Definition::Field(_)) {
293 Definition::Local(_) | Definition::Field(_) => {} 307 return None;
294 _ => return None, 308 }
295 };
296 309
297 let mode = name_ref.syntax().ancestors().find_map(|node| { 310 let mode = name_ref.syntax().ancestors().find_map(|node| {
298 match_ast! { 311 match_ast! {