|
1 | 1 | use ide_db::helpers::{for_each_tail_expr, node_ext::walk_expr, FamousDefs};
|
2 | 2 | use syntax::{
|
3 | 3 | ast::{self, Expr},
|
4 |
| - match_ast, AstNode, |
| 4 | + match_ast, AstNode, TextRange, TextSize, |
5 | 5 | };
|
6 | 6 |
|
7 | 7 | use crate::{AssistContext, AssistId, AssistKind, Assists};
|
@@ -60,25 +60,45 @@ pub(crate) fn unwrap_result_return_type(acc: &mut Assists, ctx: &AssistContext)
|
60 | 60 | });
|
61 | 61 | for_each_tail_expr(&body, tail_cb);
|
62 | 62 |
|
63 |
| - for ret_expr_arg in exprs_to_unwrap { |
64 |
| - let new_ret_expr = ret_expr_arg.to_string(); |
65 |
| - let new_ret_expr = |
66 |
| - new_ret_expr.trim_start_matches("Ok(").trim_start_matches("Err("); |
67 |
| - builder.replace( |
68 |
| - ret_expr_arg.syntax().text_range(), |
69 |
| - new_ret_expr.strip_suffix(')').unwrap_or(new_ret_expr), |
70 |
| - ) |
71 |
| - } |
72 |
| - |
| 63 | + let mut is_unit_type = false; |
73 | 64 | if let Some((_, inner_type)) = type_ref.to_string().split_once('<') {
|
74 | 65 | let inner_type = match inner_type.split_once(',') {
|
75 | 66 | Some((success_inner_type, _)) => success_inner_type,
|
76 | 67 | None => inner_type,
|
77 | 68 | };
|
78 |
| - builder.replace( |
79 |
| - type_ref.syntax().text_range(), |
80 |
| - inner_type.strip_suffix('>').unwrap_or(inner_type), |
81 |
| - ) |
| 69 | + let new_ret_type = inner_type.strip_suffix('>').unwrap_or(inner_type); |
| 70 | + if new_ret_type == "()" { |
| 71 | + is_unit_type = true; |
| 72 | + let text_range = TextRange::new( |
| 73 | + ret_type.syntax().text_range().start(), |
| 74 | + ret_type.syntax().text_range().end() + TextSize::from(1u32), |
| 75 | + ); |
| 76 | + builder.replace(text_range, "") |
| 77 | + } else { |
| 78 | + builder.replace( |
| 79 | + type_ref.syntax().text_range(), |
| 80 | + inner_type.strip_suffix('>').unwrap_or(inner_type), |
| 81 | + ) |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + for ret_expr_arg in exprs_to_unwrap { |
| 86 | + let ret_expr_str = ret_expr_arg.to_string(); |
| 87 | + if ret_expr_str.starts_with("Ok(") || ret_expr_str.starts_with("Err(") { |
| 88 | + let arg_list = ret_expr_arg.syntax().children().find_map(ast::ArgList::cast); |
| 89 | + if let Some(arg_list) = arg_list { |
| 90 | + if is_unit_type { |
| 91 | + builder.replace(ret_expr_arg.syntax().text_range(), ""); |
| 92 | + } else { |
| 93 | + let new_ret_expr = arg_list |
| 94 | + .args() |
| 95 | + .map(|arg| arg.to_string()) |
| 96 | + .collect::<Vec<String>>() |
| 97 | + .join(", "); |
| 98 | + builder.replace(ret_expr_arg.syntax().text_range(), new_ret_expr); |
| 99 | + } |
| 100 | + } |
| 101 | + } |
82 | 102 | }
|
83 | 103 | },
|
84 | 104 | )
|
@@ -126,6 +146,50 @@ fn foo() -> i32 {
|
126 | 146 | );
|
127 | 147 | }
|
128 | 148 |
|
| 149 | + #[test] |
| 150 | + fn unwrap_result_return_type_unit_type() { |
| 151 | + check_assist( |
| 152 | + unwrap_result_return_type, |
| 153 | + r#" |
| 154 | +//- minicore: result |
| 155 | +fn foo() -> Result<(), Box<dyn Error$0>> { |
| 156 | + Ok(()) |
| 157 | +} |
| 158 | +"#, |
| 159 | + r#" |
| 160 | +fn foo() { |
| 161 | + |
| 162 | +} |
| 163 | +"#, |
| 164 | + ); |
| 165 | + } |
| 166 | + |
| 167 | + #[test] |
| 168 | + fn unwrap_result_return_type_ending_with_parent() { |
| 169 | + check_assist( |
| 170 | + unwrap_result_return_type, |
| 171 | + r#" |
| 172 | +//- minicore: result |
| 173 | +fn foo() -> Result<i32, Box<dyn Error$0>> { |
| 174 | + if true { |
| 175 | + Ok(42) |
| 176 | + } else { |
| 177 | + foo() |
| 178 | + } |
| 179 | +} |
| 180 | +"#, |
| 181 | + r#" |
| 182 | +fn foo() -> i32 { |
| 183 | + if true { |
| 184 | + 42 |
| 185 | + } else { |
| 186 | + foo() |
| 187 | + } |
| 188 | +} |
| 189 | +"#, |
| 190 | + ); |
| 191 | + } |
| 192 | + |
129 | 193 | #[test]
|
130 | 194 | fn unwrap_return_type_break_split_tail() {
|
131 | 195 | check_assist(
|
|
0 commit comments