Skip to content

Commit cde189c

Browse files
Merge #6188
6188: Treat `ast::Name` in field patterns as use r=jonas-schievink a=jonas-schievink bors r+ 🤖 Co-authored-by: Jonas Schievink <[email protected]>
2 parents 95c498d + 210456a commit cde189c

File tree

2 files changed

+119
-43
lines changed

2 files changed

+119
-43
lines changed

crates/ide/src/references.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,52 @@ fn g() { f(); }
686686
);
687687
}
688688

689+
#[test]
690+
fn test_find_all_refs_struct_pat() {
691+
check(
692+
r#"
693+
struct S {
694+
field<|>: u8,
695+
}
696+
697+
fn f(s: S) {
698+
match s {
699+
S { field } => {}
700+
}
701+
}
702+
"#,
703+
expect![[r#"
704+
field RECORD_FIELD FileId(0) 15..24 15..20 Other
705+
706+
FileId(0) 68..73 FieldShorthandForField Read
707+
"#]],
708+
);
709+
}
710+
711+
#[test]
712+
fn test_find_all_refs_enum_var_pat() {
713+
check(
714+
r#"
715+
enum En {
716+
Variant {
717+
field<|>: u8,
718+
}
719+
}
720+
721+
fn f(e: En) {
722+
match e {
723+
En::Variant { field } => {}
724+
}
725+
}
726+
"#,
727+
expect![[r#"
728+
field RECORD_FIELD FileId(0) 32..41 32..37 Other
729+
730+
FileId(0) 102..107 FieldShorthandForField Read
731+
"#]],
732+
);
733+
}
734+
689735
fn check(ra_fixture: &str, expect: Expect) {
690736
check_with_scope(ra_fixture, None, expect)
691737
}

crates/ide_db/src/search.rs

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ use once_cell::unsync::Lazy;
1212
use rustc_hash::FxHashMap;
1313
use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
1414

15+
use crate::defs::NameClass;
1516
use crate::{
16-
defs::{classify_name_ref, Definition, NameRefClass},
17+
defs::{classify_name, classify_name_ref, Definition, NameRefClass},
1718
RootDatabase,
1819
};
1920

@@ -226,9 +227,9 @@ impl<'a> FindUsages<'a> {
226227

227228
let search_scope = {
228229
let base = self.def.search_scope(sema.db);
229-
match self.scope {
230+
match &self.scope {
230231
None => base,
231-
Some(scope) => base.intersection(&scope),
232+
Some(scope) => base.intersection(scope),
232233
}
233234
};
234235

@@ -251,54 +252,83 @@ impl<'a> FindUsages<'a> {
251252
continue;
252253
}
253254

254-
let name_ref: ast::NameRef =
255-
match sema.find_node_at_offset_with_descend(&tree, offset) {
256-
Some(it) => it,
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) {
255+
match sema.find_node_at_offset_with_descend(&tree, offset) {
256+
Some(name_ref) => {
257+
if self.found_name_ref(&name_ref, sink) {
276258
return;
277259
}
278260
}
279-
Some(NameRefClass::FieldShorthand { local, field }) => {
280-
let reference = match self.def {
281-
Definition::Field(_) if &field == self.def => Reference {
282-
file_range: self.sema.original_range(name_ref.syntax()),
283-
kind: ReferenceKind::FieldShorthandForField,
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;
261+
None => match sema.find_node_at_offset_with_descend(&tree, offset) {
262+
Some(name) => {
263+
if self.found_name(&name, sink) {
264+
return;
265+
}
295266
}
296-
}
297-
_ => {} // not a usage
267+
None => {}
268+
},
298269
}
299270
}
300271
}
301272
}
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+
}
302332
}
303333

304334
fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {

0 commit comments

Comments
 (0)