aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model_impl/function/scope.rs31
-rw-r--r--crates/ra_hir/src/expr.rs12
-rw-r--r--crates/ra_syntax/src/ast.rs6
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron2
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 {
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
320impl Pat { 324impl 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)
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 {
348 } 348 }
349} 349}
350 350
351impl RefPat {
352 pub fn is_mut(&self) -> bool {
353 self.syntax().children().any(|n| n.kind() == MUT_KW)
354 }
355}
356
351fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> { 357fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> {
352 children(parent).next() 358 children(parent).next()
353} 359}
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 {
2456} 2456}
2457 2457
2458 2458
2459impl RefPat {} 2459impl RefPat {
2460 pub fn pat(&self) -> Option<&Pat> {
2461 super::child_opt(self)
2462 }
2463}
2460 2464
2461// ReferenceType 2465// ReferenceType
2462#[derive(Debug, PartialEq, Eq, Hash)] 2466#[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(
462 ], 462 ],
463 ), 463 ),
464 464
465 "RefPat": (), 465 "RefPat": ( options: [ "Pat" ]),
466 "BindPat": ( traits: ["NameOwner"] ), 466 "BindPat": ( traits: ["NameOwner"] ),
467 "PlaceholderPat": (), 467 "PlaceholderPat": (),
468 "PathPat": (), 468 "PathPat": (),