Treat ast::Name in field patterns as use

This commit is contained in:
Jonas Schievink 2020-10-09 19:55:30 +02:00
parent 95c498d913
commit 210456aeaa
2 changed files with 119 additions and 43 deletions

View file

@ -686,6 +686,52 @@ fn g() { f(); }
); );
} }
#[test]
fn test_find_all_refs_struct_pat() {
check(
r#"
struct S {
field<|>: u8,
}
fn f(s: S) {
match s {
S { field } => {}
}
}
"#,
expect![[r#"
field RECORD_FIELD FileId(0) 15..24 15..20 Other
FileId(0) 68..73 FieldShorthandForField Read
"#]],
);
}
#[test]
fn test_find_all_refs_enum_var_pat() {
check(
r#"
enum En {
Variant {
field<|>: u8,
}
}
fn f(e: En) {
match e {
En::Variant { field } => {}
}
}
"#,
expect![[r#"
field RECORD_FIELD FileId(0) 32..41 32..37 Other
FileId(0) 102..107 FieldShorthandForField Read
"#]],
);
}
fn check(ra_fixture: &str, expect: Expect) { fn check(ra_fixture: &str, expect: Expect) {
check_with_scope(ra_fixture, None, expect) check_with_scope(ra_fixture, None, expect)
} }

View file

@ -12,8 +12,9 @@ use once_cell::unsync::Lazy;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
use crate::defs::NameClass;
use crate::{ use crate::{
defs::{classify_name_ref, Definition, NameRefClass}, defs::{classify_name, classify_name_ref, Definition, NameRefClass},
RootDatabase, RootDatabase,
}; };
@ -226,9 +227,9 @@ impl<'a> FindUsages<'a> {
let search_scope = { let search_scope = {
let base = self.def.search_scope(sema.db); let base = self.def.search_scope(sema.db);
match self.scope { match &self.scope {
None => base, None => base,
Some(scope) => base.intersection(&scope), Some(scope) => base.intersection(scope),
} }
}; };
@ -251,16 +252,33 @@ impl<'a> FindUsages<'a> {
continue; continue;
} }
let name_ref: ast::NameRef =
match sema.find_node_at_offset_with_descend(&tree, offset) { match sema.find_node_at_offset_with_descend(&tree, offset) {
Some(it) => it, Some(name_ref) => {
None => continue, if self.found_name_ref(&name_ref, sink) {
}; return;
}
}
None => match sema.find_node_at_offset_with_descend(&tree, offset) {
Some(name) => {
if self.found_name(&name, sink) {
return;
}
}
None => {}
},
}
}
}
}
match classify_name_ref(&sema, &name_ref) { fn found_name_ref(
&self,
name_ref: &ast::NameRef,
sink: &mut dyn FnMut(Reference) -> bool,
) -> bool {
match classify_name_ref(self.sema, &name_ref) {
Some(NameRefClass::Definition(def)) if &def == self.def => { Some(NameRefClass::Definition(def)) if &def == self.def => {
let kind = if is_record_lit_name_ref(&name_ref) let kind = if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref)
|| is_call_expr_name_ref(&name_ref)
{ {
ReferenceKind::StructLiteral ReferenceKind::StructLiteral
} else { } else {
@ -268,13 +286,11 @@ impl<'a> FindUsages<'a> {
}; };
let reference = Reference { let reference = Reference {
file_range: sema.original_range(name_ref.syntax()), file_range: self.sema.original_range(name_ref.syntax()),
kind, kind,
access: reference_access(&def, &name_ref), access: reference_access(&def, &name_ref),
}; };
if sink(reference) { sink(reference)
return;
}
} }
Some(NameRefClass::FieldShorthand { local, field }) => { Some(NameRefClass::FieldShorthand { local, field }) => {
let reference = match self.def { let reference = match self.def {
@ -288,15 +304,29 @@ impl<'a> FindUsages<'a> {
kind: ReferenceKind::FieldShorthandForLocal, kind: ReferenceKind::FieldShorthandForLocal,
access: reference_access(&Definition::Local(local), &name_ref), access: reference_access(&Definition::Local(local), &name_ref),
}, },
_ => continue, // not a usage _ => return false, // not a usage
}; };
if sink(reference) { sink(reference)
return; }
_ => false, // not a usage
} }
} }
_ => {} // not a usage
} fn found_name(&self, name: &ast::Name, sink: &mut dyn FnMut(Reference) -> bool) -> bool {
match classify_name(self.sema, name) {
Some(NameClass::FieldShorthand { local: _, field }) => {
let reference = match self.def {
Definition::Field(_) if &field == self.def => Reference {
file_range: self.sema.original_range(name.syntax()),
kind: ReferenceKind::FieldShorthandForField,
// FIXME: mutable patterns should have `Write` access
access: Some(ReferenceAccess::Read),
},
_ => return false, // not a usage
};
sink(reference)
} }
_ => false, // not a usage
} }
} }
} }