Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/extract_function.rs')
-rw-r--r--crates/ide-assists/src/handlers/extract_function.rs123
1 files changed, 59 insertions, 64 deletions
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index b8b781ea48..ea7a21e77a 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -750,7 +750,7 @@ impl FunctionBody {
.descendants_with_tokens()
.filter_map(SyntaxElement::into_token)
.filter(|it| matches!(it.kind(), SyntaxKind::IDENT | T![self]))
- .flat_map(|t| sema.descend_into_macros(t))
+ .flat_map(|t| sema.descend_into_macros(t, 0.into()))
.for_each(|t| add_name_if_local(t.parent().and_then(ast::NameRef::cast)));
}
}
@@ -810,7 +810,7 @@ impl FunctionBody {
(true, konst.body(), Some(sema.to_def(&konst)?.ty(sema.db)))
},
ast::ConstParam(cp) => {
- (true, cp.default_val(), Some(sema.to_def(&cp)?.ty(sema.db)))
+ (true, cp.default_val()?.expr(), Some(sema.to_def(&cp)?.ty(sema.db)))
},
ast::ConstBlockPat(cbp) => {
let expr = cbp.block_expr().map(ast::Expr::BlockExpr);
@@ -1385,31 +1385,30 @@ enum FlowHandler {
impl FlowHandler {
fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler {
- match &fun.control_flow.kind {
- None => FlowHandler::None,
- Some(flow_kind) => {
- let action = flow_kind.clone();
- if let FunType::Unit = ret_ty {
- match flow_kind {
- FlowKind::Return(None)
- | FlowKind::Break(_, None)
- | FlowKind::Continue(_) => FlowHandler::If { action },
- FlowKind::Return(_) | FlowKind::Break(_, _) => {
- FlowHandler::IfOption { action }
- }
- FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
- }
- } else {
- match flow_kind {
- FlowKind::Return(None)
- | FlowKind::Break(_, None)
- | FlowKind::Continue(_) => FlowHandler::MatchOption { none: action },
- FlowKind::Return(_) | FlowKind::Break(_, _) => {
- FlowHandler::MatchResult { err: action }
- }
- FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
- }
+ if fun.contains_tail_expr {
+ return FlowHandler::None;
+ }
+ let Some(action) = fun.control_flow.kind.clone() else {
+ return FlowHandler::None;
+ };
+
+ if let FunType::Unit = ret_ty {
+ match action {
+ FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
+ FlowHandler::If { action }
+ }
+ FlowKind::Return(_) | FlowKind::Break(_, _) => FlowHandler::IfOption { action },
+ FlowKind::Try { kind } => FlowHandler::Try { kind },
+ }
+ } else {
+ match action {
+ FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
+ FlowHandler::MatchOption { none: action }
+ }
+ FlowKind::Return(_) | FlowKind::Break(_, _) => {
+ FlowHandler::MatchResult { err: action }
}
+ FlowKind::Try { kind } => FlowHandler::Try { kind },
}
}
}
@@ -1654,11 +1653,7 @@ impl Function {
fn make_ret_ty(&self, ctx: &AssistContext<'_>, module: hir::Module) -> Option<ast::RetType> {
let fun_ty = self.return_type(ctx);
- let handler = if self.contains_tail_expr {
- FlowHandler::None
- } else {
- FlowHandler::from_ret_ty(self, &fun_ty)
- };
+ let handler = FlowHandler::from_ret_ty(self, &fun_ty);
let ret_ty = match &handler {
FlowHandler::None => {
if matches!(fun_ty, FunType::Unit) {
@@ -1728,11 +1723,7 @@ fn make_body(
fun: &Function,
) -> ast::BlockExpr {
let ret_ty = fun.return_type(ctx);
- let handler = if fun.contains_tail_expr {
- FlowHandler::None
- } else {
- FlowHandler::from_ret_ty(fun, &ret_ty)
- };
+ let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
let block = match &fun.body {
FunctionBody::Expr(expr) => {
@@ -4471,7 +4462,7 @@ async fn foo() -> Result<(), ()> {
"#,
r#"
async fn foo() -> Result<(), ()> {
- fun_name().await?
+ fun_name().await
}
async fn $0fun_name() -> Result<(), ()> {
@@ -4690,7 +4681,7 @@ fn $0fun_name() {
check_assist(
extract_function,
r#"
-//- minicore: result
+//- minicore: result, try
fn foo() -> Result<(), i64> {
$0Result::<i32, i64>::Ok(0)?;
Ok(())$0
@@ -4698,7 +4689,7 @@ fn foo() -> Result<(), i64> {
"#,
r#"
fn foo() -> Result<(), i64> {
- fun_name()?
+ fun_name()
}
fn $0fun_name() -> Result<(), i64> {
@@ -5754,6 +5745,34 @@ fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
}
#[test]
+ fn tail_expr_no_extra_control_flow() {
+ check_assist(
+ extract_function,
+ r#"
+//- minicore: result
+fn fallible() -> Result<(), ()> {
+ $0if true {
+ return Err(());
+ }
+ Ok(())$0
+}
+"#,
+ r#"
+fn fallible() -> Result<(), ()> {
+ fun_name()
+}
+
+fn $0fun_name() -> Result<(), ()> {
+ if true {
+ return Err(());
+ }
+ Ok(())
+}
+"#,
+ );
+ }
+
+ #[test]
fn non_tail_expr_of_tail_expr_loop() {
check_assist(
extract_function,
@@ -5800,12 +5819,6 @@ fn $0fun_name() -> ControlFlow<()> {
extract_function,
r#"
//- minicore: option, try
-impl<T> core::ops::Try for Option<T> {
- type Output = T;
- type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
fn f() -> Option<()> {
if true {
let a = $0if true {
@@ -5820,12 +5833,6 @@ fn f() -> Option<()> {
}
"#,
r#"
-impl<T> core::ops::Try for Option<T> {
- type Output = T;
- type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
fn f() -> Option<()> {
if true {
let a = fun_name()?;;
@@ -5852,12 +5859,6 @@ fn $0fun_name() -> Option<()> {
extract_function,
r#"
//- minicore: option, try
-impl<T> core::ops::Try for Option<T> {
- type Output = T;
- type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
fn f() -> Option<()> {
if true {
$0{
@@ -5874,15 +5875,9 @@ fn f() -> Option<()> {
}
"#,
r#"
-impl<T> core::ops::Try for Option<T> {
- type Output = T;
- type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
fn f() -> Option<()> {
if true {
- fun_name()?
+ fun_name()
} else {
None
}