From c4f3669e70c6b7e4bafa03f41ad29a3de46f80ad Mon Sep 17 00:00:00 2001 From: Vladyslav Katasonov Date: Thu, 4 Feb 2021 00:44:36 +0300 Subject: allow calling `&mut` methods on outer vars when extracing function --- crates/assists/src/handlers/extract_function.rs | 116 ++++++++++++++++++++++++ 1 file changed, 116 insertions(+) (limited to 'crates/assists/src') diff --git a/crates/assists/src/handlers/extract_function.rs b/crates/assists/src/handlers/extract_function.rs index a4b23d756..8a4073886 100644 --- a/crates/assists/src/handlers/extract_function.rs +++ b/crates/assists/src/handlers/extract_function.rs @@ -150,6 +150,10 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option return true; } + if is_mut_method_call(ctx, path.as_ref()).unwrap_or(false) { + return true; + } + false }); @@ -429,6 +433,17 @@ fn is_mut_ref_expr(path: Option<&ast::Expr>) -> Option { Some(ref_expr.mut_token().is_some()) } +fn is_mut_method_call(ctx: &AssistContext, path: Option<&ast::Expr>) -> Option { + let path = path?; + let method_call = path.syntax().parent().and_then(ast::MethodCallExpr::cast)?; + + let func = ctx.sema.resolve_method_call(&method_call)?; + let self_param = func.self_param(ctx.db())?; + let access = self_param.access(ctx.db()); + + Some(matches!(access, hir::Access::Exclusive)) +} + fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode { let mut rewriter = SyntaxRewriter::default(); for param in params { @@ -1507,6 +1522,107 @@ fn foo() { fn $0fun_name(mut n: i32) { let v = &mut n; *v += 1; +}", + ); + } + + #[test] + fn mut_method_call() { + check_assist( + extract_function, + r" +trait I { + fn inc(&mut self); +} +impl I for i32 { + fn inc(&mut self) { *self += 1 } +} +fn foo() { + let mut n = 1; + $0n.inc();$0 +}", + r" +trait I { + fn inc(&mut self); +} +impl I for i32 { + fn inc(&mut self) { *self += 1 } +} +fn foo() { + let mut n = 1; + fun_name(n); +} + +fn $0fun_name(mut n: i32) { + n.inc(); +}", + ); + } + + #[test] + fn shared_method_call() { + check_assist( + extract_function, + r" +trait I { + fn succ(&self); +} +impl I for i32 { + fn succ(&self) { *self + 1 } +} +fn foo() { + let mut n = 1; + $0n.succ();$0 +}", + r" +trait I { + fn succ(&self); +} +impl I for i32 { + fn succ(&self) { *self + 1 } +} +fn foo() { + let mut n = 1; + fun_name(n); +} + +fn $0fun_name(n: i32) { + n.succ(); +}", + ); + } + + #[test] + fn mut_method_call_with_other_receiver() { + check_assist( + extract_function, + r" +trait I { + fn inc(&mut self, n: i32); +} +impl I for i32 { + fn inc(&mut self, n: i32) { *self += n } +} +fn foo() { + let mut n = 1; + $0let mut m = 2; + m.inc(n);$0 +}", + r" +trait I { + fn inc(&mut self, n: i32); +} +impl I for i32 { + fn inc(&mut self, n: i32) { *self += n } +} +fn foo() { + let mut n = 1; + fun_name(n); +} + +fn $0fun_name(n: i32) { + let mut m = 2; + m.inc(n); }", ); } -- cgit v1.2.3