Wrap inlined closures in parens when inlined in an expression in inline_call

This commit is contained in:
Lukas Wirth 2021-07-05 15:34:01 +02:00
parent 2579dc6d82
commit dafbe6940e
3 changed files with 68 additions and 8 deletions

View file

@ -14,7 +14,9 @@ use crate::{
// Assist: inline_call // Assist: inline_call
// //
// Inlines a function or method body. // Inlines a function or method body creating a `let` statement per parameter unless the parameter
// can be inlined. The parameter will be inlined either if it the supplied argument is a simple local
// or if the parameter is only accessed inside the function body once.
// //
// ``` // ```
// # //- minicore: option // # //- minicore: option
@ -132,7 +134,7 @@ pub(crate) fn inline_(
.covering_element(range) .covering_element(range)
.ancestors() .ancestors()
.nth(3) .nth(3)
.filter(|it| ast::PathExpr::can_cast(it.kind())), .and_then(ast::PathExpr::cast),
_ => None, _ => None,
}) })
.collect::<Option<Vec<_>>>() .collect::<Option<Vec<_>>>()
@ -158,7 +160,14 @@ pub(crate) fn inline_(
match &*usages { match &*usages {
// inline single use parameters // inline single use parameters
[usage] => { [usage] => {
ted::replace(usage, expr.syntax().clone_for_update()); let expr = if matches!(expr, ast::Expr::ClosureExpr(_))
&& usage.syntax().parent().and_then(ast::Expr::cast).is_some()
{
make::expr_paren(expr)
} else {
expr
};
ted::replace(usage.syntax(), expr.syntax().clone_for_update());
} }
// inline parameters whose expression is a simple local reference // inline parameters whose expression is a simple local reference
[_, ..] [_, ..]
@ -168,7 +177,7 @@ pub(crate) fn inline_(
) => ) =>
{ {
usages.into_iter().for_each(|usage| { usages.into_iter().for_each(|usage| {
ted::replace(usage, &expr.syntax().clone_for_update()); ted::replace(usage.syntax(), &expr.syntax().clone_for_update());
}); });
} }
// cant inline, emit a let statement // cant inline, emit a let statement
@ -535,6 +544,56 @@ impl Foo {
}; };
} }
} }
"#,
);
}
#[test]
fn wraps_closure_in_paren() {
check_assist(
inline_call,
r#"
fn foo(x: fn()) {
x();
}
fn main() {
foo$0(|| {})
}
"#,
r#"
fn foo(x: fn()) {
x();
}
fn main() {
{
(|| {})();
}
}
"#,
);
check_assist(
inline_call,
r#"
fn foo(x: fn()) {
x();
}
fn main() {
foo$0(main)
}
"#,
r#"
fn foo(x: fn()) {
x();
}
fn main() {
{
main();
}
}
"#, "#,
); );
} }

View file

@ -1,4 +1,7 @@
//! Handle syntactic aspects of inserting a new `use`. //! Handle syntactic aspects of inserting a new `use`.
#[cfg(test)]
mod tests;
use std::cmp::Ordering; use std::cmp::Ordering;
use hir::Semantics; use hir::Semantics;
@ -378,5 +381,3 @@ fn is_inner_comment(token: SyntaxToken) -> bool {
ast::Comment::cast(token).and_then(|comment| comment.kind().doc) ast::Comment::cast(token).and_then(|comment| comment.kind().doc)
== Some(ast::CommentPlacement::Inner) == Some(ast::CommentPlacement::Inner)
} }
#[cfg(test)]
mod tests;

View file

@ -14,7 +14,7 @@ fn foo() {$0}
r#" r#"
#[cfg(test)] #[cfg(test)]
fn foo() { fn foo() {
use bar::Bar; use bar::Bar;
} }
"#, "#,
ImportGranularity::Crate, ImportGranularity::Crate,
@ -32,7 +32,7 @@ const FOO: Bar = {$0};
r#" r#"
#[cfg(test)] #[cfg(test)]
const FOO: Bar = { const FOO: Bar = {
use bar::Bar; use bar::Bar;
}; };
"#, "#,
ImportGranularity::Crate, ImportGranularity::Crate,