Merge #9497
9497: Wrap inlined closures in parens when inlined in an expression in `inline_call` r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
ac300eaceb
@ -14,26 +14,23 @@
|
|||||||
|
|
||||||
// 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.
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
// fn align(a: u32, b: u32) -> u32 {
|
// # //- minicore: option
|
||||||
// (a + b - 1) & !(b - 1)
|
// fn foo(name: Option<&str>) {
|
||||||
// }
|
// let name = name.unwrap$0();
|
||||||
// fn main() {
|
|
||||||
// let x = align$0(1, 2);
|
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
// ->
|
// ->
|
||||||
// ```
|
// ```
|
||||||
// fn align(a: u32, b: u32) -> u32 {
|
// fn foo(name: Option<&str>) {
|
||||||
// (a + b - 1) & !(b - 1)
|
// let name = match name {
|
||||||
// }
|
// Some(val) => val,
|
||||||
// fn main() {
|
// None => panic!("called `Option::unwrap()` on a `None` value"),
|
||||||
// let x = {
|
// };
|
||||||
// let b = 2;
|
|
||||||
// (1 + b - 1) & !(b - 1)
|
|
||||||
// };
|
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||||
@ -137,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<_>>>()
|
||||||
@ -163,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
|
||||||
[_, ..]
|
[_, ..]
|
||||||
@ -173,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
|
||||||
@ -540,6 +544,56 @@ fn bar(&self) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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();
|
||||||
|
}
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -923,22 +923,17 @@ fn doctest_inline_call() {
|
|||||||
check_doc_test(
|
check_doc_test(
|
||||||
"inline_call",
|
"inline_call",
|
||||||
r#####"
|
r#####"
|
||||||
fn align(a: u32, b: u32) -> u32 {
|
//- minicore: option
|
||||||
(a + b - 1) & !(b - 1)
|
fn foo(name: Option<&str>) {
|
||||||
}
|
let name = name.unwrap$0();
|
||||||
fn main() {
|
|
||||||
let x = align$0(1, 2);
|
|
||||||
}
|
}
|
||||||
"#####,
|
"#####,
|
||||||
r#####"
|
r#####"
|
||||||
fn align(a: u32, b: u32) -> u32 {
|
fn foo(name: Option<&str>) {
|
||||||
(a + b - 1) & !(b - 1)
|
let name = match name {
|
||||||
}
|
Some(val) => val,
|
||||||
fn main() {
|
None => panic!("called `Option::unwrap()` on a `None` value"),
|
||||||
let x = {
|
};
|
||||||
let b = 2;
|
|
||||||
(1 + b - 1) & !(b - 1)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
"#####,
|
"#####,
|
||||||
)
|
)
|
||||||
|
@ -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;
|
|
||||||
|
@ -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 @@ fn respects_cfg_attr_const() {
|
|||||||
r#"
|
r#"
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
const FOO: Bar = {
|
const FOO: Bar = {
|
||||||
use bar::Bar;
|
use bar::Bar;
|
||||||
};
|
};
|
||||||
"#,
|
"#,
|
||||||
ImportGranularity::Crate,
|
ImportGranularity::Crate,
|
||||||
|
@ -161,6 +161,14 @@ fn ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if prev.kind() == T!['{'] && ast::Stmt::can_cast(new.kind()) {
|
||||||
|
if let Some(block_expr) = prev.parent().and_then(ast::BlockExpr::cast) {
|
||||||
|
let mut indent = IndentLevel::from_element(&block_expr.syntax().clone().into());
|
||||||
|
indent.0 += 1;
|
||||||
|
return Some(make::tokens::whitespace(&format!("\n{}", indent)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ws_between(prev, new)
|
ws_between(prev, new)
|
||||||
}
|
}
|
||||||
fn ws_after(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> {
|
fn ws_after(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> {
|
||||||
@ -187,12 +195,6 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if left.kind() == T!['{'] && right.kind() == SyntaxKind::LET_STMT {
|
|
||||||
let mut indent = IndentLevel::from_element(left);
|
|
||||||
indent.0 += 1;
|
|
||||||
return Some(make::tokens::whitespace(&format!("\n{}", indent)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if right.kind() == SyntaxKind::USE {
|
if right.kind() == SyntaxKind::USE {
|
||||||
let mut indent = IndentLevel::from_element(left);
|
let mut indent = IndentLevel::from_element(left);
|
||||||
if left.kind() == SyntaxKind::USE {
|
if left.kind() == SyntaxKind::USE {
|
||||||
|
@ -330,6 +330,15 @@ pub enum Option<T> {
|
|||||||
#[lang = "Some"]
|
#[lang = "Some"]
|
||||||
Some(T),
|
Some(T),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Option<T> {
|
||||||
|
pub const fn unwrap(self) -> T {
|
||||||
|
match self {
|
||||||
|
Some(val) => val,
|
||||||
|
None => panic!("called `Option::unwrap()` on a `None` value"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// endregion:option
|
// endregion:option
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user