From 8e554ea5faa1158e084462162d5e1932db5c81c2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 13 Jan 2019 13:34:57 +0300 Subject: support ref-patterns --- .../ra_hir/src/code_model_impl/function/scope.rs | 31 ++++++++++++++++------ crates/ra_hir/src/expr.rs | 12 ++++++++- crates/ra_syntax/src/ast.rs | 6 +++++ crates/ra_syntax/src/ast/generated.rs | 6 ++++- crates/ra_syntax/src/grammar.ron | 2 +- 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/code_model_impl/function/scope.rs index 7d938c0dd..afca1e9f8 100644 --- a/crates/ra_hir/src/code_model_impl/function/scope.rs +++ b/crates/ra_hir/src/code_model_impl/function/scope.rs @@ -422,6 +422,9 @@ mod tests { fn do_check_local_name(code: &str, expected_offset: u32) { let (off, code) = extract_offset(code); let file = SourceFile::parse(&code); + let expected_name = find_node_at_offset::(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 name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); @@ -431,11 +434,8 @@ mod tests { scopes: Arc::new(scopes), syntax_mapping: Arc::new(body_hir), }; - let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); let local_name = local_name_entry.ptr(); - let expected_name = - find_node_at_offset::(file.syntax(), expected_offset.into()).unwrap(); assert_eq!(local_name.range(), expected_name.syntax().range()); } @@ -470,11 +470,26 @@ mod tests { fn test_resolve_local_name_shadow() { do_check_local_name( r" - fn foo(x: String) { - let x : &str = &x; - x<|> - }", - 46, + fn foo(x: String) { + let x : &str = &x; + x<|> + } + ", + 53, + ); + } + + #[test] + fn ref_patterns_contribute_bindings() { + do_check_local_name( + r" + fn foo() { + if let Some(&from) = bar() { + from<|>; + } + } + ", + 53, ); } } diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 67e123e4d..593fe1598 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -315,15 +315,20 @@ pub enum Pat { path: Option, args: Vec, }, + Ref { + pat: PatId, + mutability: Mutability, + }, } 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 { Pat::Missing | Pat::Bind { .. } => {} Pat::TupleStruct { args, .. } => { 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(); 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 self.alloc_pat(Pat::Missing, syntax_ptr) diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 123a7a6b9..8bf439b60 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -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(parent: &P) -> Option<&C> { children(parent).next() } diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 1f6055115..f745cb1cb 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -2456,7 +2456,11 @@ impl AstNode for RefPat { } -impl RefPat {} +impl RefPat { + pub fn pat(&self) -> Option<&Pat> { + super::child_opt(self) + } +} // ReferenceType #[derive(Debug, PartialEq, Eq, Hash)] diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index bddd96a5c..bac62fa04 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -462,7 +462,7 @@ Grammar( ], ), - "RefPat": (), + "RefPat": ( options: [ "Pat" ]), "BindPat": ( traits: ["NameOwner"] ), "PlaceholderPat": (), "PathPat": (), -- cgit v1.2.3