aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-10-09 18:55:30 +0100
committerJonas Schievink <[email protected]>2020-10-09 18:56:54 +0100
commit210456aeaa44bb970bf4ce28eba3e8c6890bc38d (patch)
tree604b171de5aed9d3c4eeb885929b80f60d32397c /crates/ide_db
parent95c498d913a2aec1b97ae3613290e7d7a104d0e4 (diff)
Treat `ast::Name` in field patterns as use
Diffstat (limited to 'crates/ide_db')
-rw-r--r--crates/ide_db/src/search.rs116
1 files changed, 73 insertions, 43 deletions
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index edab1d644..8e3dcd99c 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -12,8 +12,9 @@ use once_cell::unsync::Lazy;
12use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
13use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; 13use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
14 14
15use crate::defs::NameClass;
15use crate::{ 16use crate::{
16 defs::{classify_name_ref, Definition, NameRefClass}, 17 defs::{classify_name, classify_name_ref, Definition, NameRefClass},
17 RootDatabase, 18 RootDatabase,
18}; 19};
19 20
@@ -226,9 +227,9 @@ impl<'a> FindUsages<'a> {
226 227
227 let search_scope = { 228 let search_scope = {
228 let base = self.def.search_scope(sema.db); 229 let base = self.def.search_scope(sema.db);
229 match self.scope { 230 match &self.scope {
230 None => base, 231 None => base,
231 Some(scope) => base.intersection(&scope), 232 Some(scope) => base.intersection(scope),
232 } 233 }
233 }; 234 };
234 235
@@ -251,54 +252,83 @@ impl<'a> FindUsages<'a> {
251 continue; 252 continue;
252 } 253 }
253 254
254 let name_ref: ast::NameRef = 255 match sema.find_node_at_offset_with_descend(&tree, offset) {
255 match sema.find_node_at_offset_with_descend(&tree, offset) { 256 Some(name_ref) => {
256 Some(it) => it, 257 if self.found_name_ref(&name_ref, sink) {
257 None => continue,
258 };
259
260 match classify_name_ref(&sema, &name_ref) {
261 Some(NameRefClass::Definition(def)) if &def == self.def => {
262 let kind = if is_record_lit_name_ref(&name_ref)
263 || is_call_expr_name_ref(&name_ref)
264 {
265 ReferenceKind::StructLiteral
266 } else {
267 ReferenceKind::Other
268 };
269
270 let reference = Reference {
271 file_range: sema.original_range(name_ref.syntax()),
272 kind,
273 access: reference_access(&def, &name_ref),
274 };
275 if sink(reference) {
276 return; 258 return;
277 } 259 }
278 } 260 }
279 Some(NameRefClass::FieldShorthand { local, field }) => { 261 None => match sema.find_node_at_offset_with_descend(&tree, offset) {
280 let reference = match self.def { 262 Some(name) => {
281 Definition::Field(_) if &field == self.def => Reference { 263 if self.found_name(&name, sink) {
282 file_range: self.sema.original_range(name_ref.syntax()), 264 return;
283 kind: ReferenceKind::FieldShorthandForField, 265 }
284 access: reference_access(&field, &name_ref),
285 },
286 Definition::Local(l) if &local == l => Reference {
287 file_range: self.sema.original_range(name_ref.syntax()),
288 kind: ReferenceKind::FieldShorthandForLocal,
289 access: reference_access(&Definition::Local(local), &name_ref),
290 },
291 _ => continue, // not a usage
292 };
293 if sink(reference) {
294 return;
295 } 266 }
296 } 267 None => {}
297 _ => {} // not a usage 268 },
298 } 269 }
299 } 270 }
300 } 271 }
301 } 272 }
273
274 fn found_name_ref(
275 &self,
276 name_ref: &ast::NameRef,
277 sink: &mut dyn FnMut(Reference) -> bool,
278 ) -> bool {
279 match classify_name_ref(self.sema, &name_ref) {
280 Some(NameRefClass::Definition(def)) if &def == self.def => {
281 let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref)
282 {
283 ReferenceKind::StructLiteral
284 } else {
285 ReferenceKind::Other
286 };
287
288 let reference = Reference {
289 file_range: self.sema.original_range(name_ref.syntax()),
290 kind,
291 access: reference_access(&def, &name_ref),
292 };
293 sink(reference)
294 }
295 Some(NameRefClass::FieldShorthand { local, field }) => {
296 let reference = match self.def {
297 Definition::Field(_) if &field == self.def => Reference {
298 file_range: self.sema.original_range(name_ref.syntax()),
299 kind: ReferenceKind::FieldShorthandForField,
300 access: reference_access(&field, &name_ref),
301 },
302 Definition::Local(l) if &local == l => Reference {
303 file_range: self.sema.original_range(name_ref.syntax()),
304 kind: ReferenceKind::FieldShorthandForLocal,
305 access: reference_access(&Definition::Local(local), &name_ref),
306 },
307 _ => return false, // not a usage
308 };
309 sink(reference)
310 }
311 _ => false, // not a usage
312 }
313 }
314
315 fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool {
316 match classify_name(self.sema, name) {
317 Some(NameClass::FieldShorthand { local: _, field }) => {
318 let reference = match self.def {
319 Definition::Field(_) if &field == self.def => Reference {
320 file_range: self.sema.original_range(name.syntax()),
321 kind: ReferenceKind::FieldShorthandForField,
322 // FIXME: mutable patterns should have `Write` access
323 access: Some(ReferenceAccess::Read),
324 },
325 _ => return false, // not a usage
326 };
327 sink(reference)
328 }
329 _ => false, // not a usage
330 }
331 }
302} 332}
303 333
304fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { 334fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {