diff options
author | Aleksey Kladov <[email protected]> | 2019-01-13 10:34:57 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-13 10:36:06 +0000 |
commit | 8e554ea5faa1158e084462162d5e1932db5c81c2 (patch) | |
tree | a24233c5a007f3d089f4fd369a0c5e8f92e0af00 /crates/ra_hir/src | |
parent | 40686722ba0762c4af396da120331710edfeabe8 (diff) |
support ref-patterns
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model_impl/function/scope.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 12 |
2 files changed, 34 insertions, 9 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 { | |||
422 | fn do_check_local_name(code: &str, expected_offset: u32) { | 422 | fn do_check_local_name(code: &str, expected_offset: u32) { |
423 | let (off, code) = extract_offset(code); | 423 | let (off, code) = extract_offset(code); |
424 | let file = SourceFile::parse(&code); | 424 | let file = SourceFile::parse(&code); |
425 | let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) | ||
426 | .expect("failed to find a name at the target offset"); | ||
427 | |||
425 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); | 428 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); |
426 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); | 429 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); |
427 | 430 | ||
@@ -431,11 +434,8 @@ mod tests { | |||
431 | scopes: Arc::new(scopes), | 434 | scopes: Arc::new(scopes), |
432 | syntax_mapping: Arc::new(body_hir), | 435 | syntax_mapping: Arc::new(body_hir), |
433 | }; | 436 | }; |
434 | |||
435 | let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); | 437 | let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); |
436 | let local_name = local_name_entry.ptr(); | 438 | let local_name = local_name_entry.ptr(); |
437 | let expected_name = | ||
438 | find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap(); | ||
439 | assert_eq!(local_name.range(), expected_name.syntax().range()); | 439 | assert_eq!(local_name.range(), expected_name.syntax().range()); |
440 | } | 440 | } |
441 | 441 | ||
@@ -470,11 +470,26 @@ mod tests { | |||
470 | fn test_resolve_local_name_shadow() { | 470 | fn test_resolve_local_name_shadow() { |
471 | do_check_local_name( | 471 | do_check_local_name( |
472 | r" | 472 | r" |
473 | fn foo(x: String) { | 473 | fn foo(x: String) { |
474 | let x : &str = &x; | 474 | let x : &str = &x; |
475 | x<|> | 475 | x<|> |
476 | }", | 476 | } |
477 | 46, | 477 | ", |
478 | 53, | ||
479 | ); | ||
480 | } | ||
481 | |||
482 | #[test] | ||
483 | fn ref_patterns_contribute_bindings() { | ||
484 | do_check_local_name( | ||
485 | r" | ||
486 | fn foo() { | ||
487 | if let Some(&from) = bar() { | ||
488 | from<|>; | ||
489 | } | ||
490 | } | ||
491 | ", | ||
492 | 53, | ||
478 | ); | 493 | ); |
479 | } | 494 | } |
480 | } | 495 | } |
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 { | |||
315 | path: Option<Path>, | 315 | path: Option<Path>, |
316 | args: Vec<PatId>, | 316 | args: Vec<PatId>, |
317 | }, | 317 | }, |
318 | Ref { | ||
319 | pat: PatId, | ||
320 | mutability: Mutability, | ||
321 | }, | ||
318 | } | 322 | } |
319 | 323 | ||
320 | impl Pat { | 324 | impl Pat { |
321 | pub fn walk_child_pats(&self, f: impl FnMut(PatId)) { | 325 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { |
322 | match self { | 326 | match self { |
323 | Pat::Missing | Pat::Bind { .. } => {} | 327 | Pat::Missing | Pat::Bind { .. } => {} |
324 | Pat::TupleStruct { args, .. } => { | 328 | Pat::TupleStruct { args, .. } => { |
325 | args.iter().map(|pat| *pat).for_each(f); | 329 | args.iter().map(|pat| *pat).for_each(f); |
326 | } | 330 | } |
331 | Pat::Ref { pat, .. } => f(*pat), | ||
327 | } | 332 | } |
328 | } | 333 | } |
329 | } | 334 | } |
@@ -684,6 +689,11 @@ impl ExprCollector { | |||
684 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 689 | let args = p.args().map(|p| self.collect_pat(p)).collect(); |
685 | self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr) | 690 | self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr) |
686 | } | 691 | } |
692 | ast::PatKind::RefPat(p) => { | ||
693 | let pat = self.collect_pat_opt(p.pat()); | ||
694 | let mutability = Mutability::from_mutable(p.is_mut()); | ||
695 | self.alloc_pat(Pat::Ref { pat, mutability }, syntax_ptr) | ||
696 | } | ||
687 | _ => { | 697 | _ => { |
688 | // TODO | 698 | // TODO |
689 | self.alloc_pat(Pat::Missing, syntax_ptr) | 699 | self.alloc_pat(Pat::Missing, syntax_ptr) |