mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
support ref-patterns
This commit is contained in:
parent
40686722ba
commit
8e554ea5fa
@ -422,6 +422,9 @@ mod tests {
|
|||||||
fn do_check_local_name(code: &str, expected_offset: u32) {
|
fn do_check_local_name(code: &str, expected_offset: u32) {
|
||||||
let (off, code) = extract_offset(code);
|
let (off, code) = extract_offset(code);
|
||||||
let file = SourceFile::parse(&code);
|
let file = SourceFile::parse(&code);
|
||||||
|
let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into())
|
||||||
|
.expect("failed to find a name at the target offset");
|
||||||
|
|
||||||
let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
|
let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
|
||||||
let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
|
let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
|
||||||
|
|
||||||
@ -431,11 +434,8 @@ mod tests {
|
|||||||
scopes: Arc::new(scopes),
|
scopes: Arc::new(scopes),
|
||||||
syntax_mapping: Arc::new(body_hir),
|
syntax_mapping: Arc::new(body_hir),
|
||||||
};
|
};
|
||||||
|
|
||||||
let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
|
let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
|
||||||
let local_name = local_name_entry.ptr();
|
let local_name = local_name_entry.ptr();
|
||||||
let expected_name =
|
|
||||||
find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap();
|
|
||||||
assert_eq!(local_name.range(), expected_name.syntax().range());
|
assert_eq!(local_name.range(), expected_name.syntax().range());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,11 +470,26 @@ mod tests {
|
|||||||
fn test_resolve_local_name_shadow() {
|
fn test_resolve_local_name_shadow() {
|
||||||
do_check_local_name(
|
do_check_local_name(
|
||||||
r"
|
r"
|
||||||
fn foo(x: String) {
|
fn foo(x: String) {
|
||||||
let x : &str = &x;
|
let x : &str = &x;
|
||||||
x<|>
|
x<|>
|
||||||
}",
|
}
|
||||||
46,
|
",
|
||||||
|
53,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ref_patterns_contribute_bindings() {
|
||||||
|
do_check_local_name(
|
||||||
|
r"
|
||||||
|
fn foo() {
|
||||||
|
if let Some(&from) = bar() {
|
||||||
|
from<|>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
",
|
||||||
|
53,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,15 +315,20 @@ pub enum Pat {
|
|||||||
path: Option<Path>,
|
path: Option<Path>,
|
||||||
args: Vec<PatId>,
|
args: Vec<PatId>,
|
||||||
},
|
},
|
||||||
|
Ref {
|
||||||
|
pat: PatId,
|
||||||
|
mutability: Mutability,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pat {
|
impl Pat {
|
||||||
pub fn walk_child_pats(&self, f: impl FnMut(PatId)) {
|
pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
|
||||||
match self {
|
match self {
|
||||||
Pat::Missing | Pat::Bind { .. } => {}
|
Pat::Missing | Pat::Bind { .. } => {}
|
||||||
Pat::TupleStruct { args, .. } => {
|
Pat::TupleStruct { args, .. } => {
|
||||||
args.iter().map(|pat| *pat).for_each(f);
|
args.iter().map(|pat| *pat).for_each(f);
|
||||||
}
|
}
|
||||||
|
Pat::Ref { pat, .. } => f(*pat),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,6 +689,11 @@ impl ExprCollector {
|
|||||||
let args = p.args().map(|p| self.collect_pat(p)).collect();
|
let args = p.args().map(|p| self.collect_pat(p)).collect();
|
||||||
self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr)
|
self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr)
|
||||||
}
|
}
|
||||||
|
ast::PatKind::RefPat(p) => {
|
||||||
|
let pat = self.collect_pat_opt(p.pat());
|
||||||
|
let mutability = Mutability::from_mutable(p.is_mut());
|
||||||
|
self.alloc_pat(Pat::Ref { pat, mutability }, syntax_ptr)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// TODO
|
// TODO
|
||||||
self.alloc_pat(Pat::Missing, syntax_ptr)
|
self.alloc_pat(Pat::Missing, syntax_ptr)
|
||||||
|
@ -348,6 +348,12 @@ impl UseTreeList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RefPat {
|
||||||
|
pub fn is_mut(&self) -> bool {
|
||||||
|
self.syntax().children().any(|n| n.kind() == MUT_KW)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> {
|
fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> {
|
||||||
children(parent).next()
|
children(parent).next()
|
||||||
}
|
}
|
||||||
|
@ -2456,7 +2456,11 @@ impl AstNode for RefPat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl RefPat {}
|
impl RefPat {
|
||||||
|
pub fn pat(&self) -> Option<&Pat> {
|
||||||
|
super::child_opt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ReferenceType
|
// ReferenceType
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -462,7 +462,7 @@ Grammar(
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
"RefPat": (),
|
"RefPat": ( options: [ "Pat" ]),
|
||||||
"BindPat": ( traits: ["NameOwner"] ),
|
"BindPat": ( traits: ["NameOwner"] ),
|
||||||
"PlaceholderPat": (),
|
"PlaceholderPat": (),
|
||||||
"PathPat": (),
|
"PathPat": (),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user