@@ -30,33 +30,33 @@ use crate::{AssistContext, Assists};
30
30
pub ( crate ) fn replace_or_with_or_else ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
31
31
let call: ast:: MethodCallExpr = ctx. find_node_at_offset ( ) ?;
32
32
33
- is_option_or_result ( call. receiver ( ) ?, ctx) ?;
33
+ let kind = is_option_or_result ( call. receiver ( ) ?, ctx) ?;
34
34
35
35
let ( name, arg_list) = ( call. name_ref ( ) ?, call. arg_list ( ) ?) ;
36
36
37
+ let mut map_or = false ;
38
+
37
39
let replace = match & * name. text ( ) {
38
40
"unwrap_or" => "unwrap_or_else" . to_string ( ) ,
39
- "ok_or" => "ok_or_else" . to_string ( ) ,
41
+ "or" => "or_else" . to_string ( ) ,
42
+ "ok_or" if kind == Kind :: Option => "ok_or_else" . to_string ( ) ,
43
+ "map_or" => {
44
+ map_or = true ;
45
+ "map_or_else" . to_string ( )
46
+ }
40
47
_ => return None ,
41
48
} ;
42
49
43
50
let arg = match arg_list. args ( ) . collect :: < Vec < _ > > ( ) . as_slice ( ) {
44
51
[ ] => make:: arg_list ( Vec :: new ( ) ) ,
45
52
[ first] => {
46
- let param = ( || {
47
- if let ast:: Expr :: CallExpr ( call) = first {
48
- if call. arg_list ( ) ?. args ( ) . count ( ) == 0 {
49
- Some ( call. expr ( ) ?. clone ( ) )
50
- } else {
51
- None
52
- }
53
- } else {
54
- None
55
- }
56
- } ) ( )
57
- . unwrap_or_else ( || make:: expr_closure ( None , first. clone ( ) ) ) ;
53
+ let param = into_closure ( first) ;
58
54
make:: arg_list ( vec ! [ param] )
59
55
}
56
+ [ first, second] if map_or => {
57
+ let param = into_closure ( first) ;
58
+ make:: arg_list ( vec ! [ param, second. clone( ) ] )
59
+ }
60
60
_ => return None ,
61
61
} ;
62
62
@@ -71,6 +71,21 @@ pub(crate) fn replace_or_with_or_else(acc: &mut Assists, ctx: &AssistContext<'_>
71
71
)
72
72
}
73
73
74
+ fn into_closure ( param : & Expr ) -> Expr {
75
+ ( || {
76
+ if let ast:: Expr :: CallExpr ( call) = param {
77
+ if call. arg_list ( ) ?. args ( ) . count ( ) == 0 {
78
+ Some ( call. expr ( ) ?. clone ( ) )
79
+ } else {
80
+ None
81
+ }
82
+ } else {
83
+ None
84
+ }
85
+ } ) ( )
86
+ . unwrap_or_else ( || make:: expr_closure ( None , param. clone ( ) ) )
87
+ }
88
+
74
89
// Assist: replace_or_else_with_or
75
90
//
76
91
// Replace `unwrap_or_else` with `unwrap_or` and `ok_or_else` with `ok_or`.
@@ -92,33 +107,32 @@ pub(crate) fn replace_or_with_or_else(acc: &mut Assists, ctx: &AssistContext<'_>
92
107
pub ( crate ) fn replace_or_else_with_or ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
93
108
let call: ast:: MethodCallExpr = ctx. find_node_at_offset ( ) ?;
94
109
95
- is_option_or_result ( call. receiver ( ) ?, ctx) ?;
110
+ let kind = is_option_or_result ( call. receiver ( ) ?, ctx) ?;
96
111
97
112
let ( name, arg_list) = ( call. name_ref ( ) ?, call. arg_list ( ) ?) ;
98
113
114
+ let mut map_or = false ;
99
115
let replace = match & * name. text ( ) {
100
116
"unwrap_or_else" => "unwrap_or" . to_string ( ) ,
101
- "ok_or_else" => "ok_or" . to_string ( ) ,
117
+ "or_else" => "or" . to_string ( ) ,
118
+ "ok_or_else" if kind == Kind :: Option => "ok_or" . to_string ( ) ,
119
+ "map_or_else" => {
120
+ map_or = true ;
121
+ "map_or" . to_string ( )
122
+ }
102
123
_ => return None ,
103
124
} ;
104
125
105
126
let arg = match arg_list. args ( ) . collect :: < Vec < _ > > ( ) . as_slice ( ) {
106
127
[ ] => make:: arg_list ( Vec :: new ( ) ) ,
107
128
[ first] => {
108
- let param = ( || {
109
- if let ast:: Expr :: ClosureExpr ( closure) = first {
110
- if closure. param_list ( ) ?. params ( ) . count ( ) == 0 {
111
- Some ( closure. body ( ) ?. clone ( ) )
112
- } else {
113
- None
114
- }
115
- } else {
116
- None
117
- }
118
- } ) ( )
119
- . unwrap_or_else ( || make:: expr_call ( first. clone ( ) , make:: arg_list ( Vec :: new ( ) ) ) ) ;
129
+ let param = into_call ( first) ;
120
130
make:: arg_list ( vec ! [ param] )
121
131
}
132
+ [ first, second] if map_or => {
133
+ let param = into_call ( first) ;
134
+ make:: arg_list ( vec ! [ param, second. clone( ) ] )
135
+ }
122
136
_ => return None ,
123
137
} ;
124
138
@@ -133,14 +147,35 @@ pub(crate) fn replace_or_else_with_or(acc: &mut Assists, ctx: &AssistContext<'_>
133
147
)
134
148
}
135
149
136
- fn is_option_or_result ( receiver : Expr , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
150
+ fn into_call ( param : & Expr ) -> Expr {
151
+ ( || {
152
+ if let ast:: Expr :: ClosureExpr ( closure) = param {
153
+ if closure. param_list ( ) ?. params ( ) . count ( ) == 0 {
154
+ Some ( closure. body ( ) ?. clone ( ) )
155
+ } else {
156
+ None
157
+ }
158
+ } else {
159
+ None
160
+ }
161
+ } ) ( )
162
+ . unwrap_or_else ( || make:: expr_call ( param. clone ( ) , make:: arg_list ( Vec :: new ( ) ) ) )
163
+ }
164
+
165
+ #[ derive( PartialEq , Eq ) ]
166
+ enum Kind {
167
+ Option ,
168
+ Result ,
169
+ }
170
+
171
+ fn is_option_or_result ( receiver : Expr , ctx : & AssistContext < ' _ > ) -> Option < Kind > {
137
172
let ty = ctx. sema . type_of_expr ( & receiver) ?. adjusted ( ) . as_adt ( ) ?. as_enum ( ) ?;
138
173
let option_enum =
139
174
FamousDefs ( & ctx. sema , ctx. sema . scope ( receiver. syntax ( ) ) ?. krate ( ) ) . core_option_Option ( ) ;
140
175
141
176
if let Some ( option_enum) = option_enum {
142
177
if ty == option_enum {
143
- return Some ( ( ) ) ;
178
+ return Some ( Kind :: Option ) ;
144
179
}
145
180
}
146
181
@@ -149,7 +184,7 @@ fn is_option_or_result(receiver: Expr, ctx: &AssistContext<'_>) -> Option<()> {
149
184
150
185
if let Some ( result_enum) = result_enum {
151
186
if ty == result_enum {
152
- return Some ( ( ) ) ;
187
+ return Some ( Kind :: Result ) ;
153
188
}
154
189
}
155
190
@@ -294,6 +329,26 @@ fn foo() {
294
329
)
295
330
}
296
331
332
+ #[ test]
333
+ fn replace_or_else_with_or_map ( ) {
334
+ check_assist (
335
+ replace_or_else_with_or,
336
+ r#"
337
+ //- minicore: result
338
+ fn foo() {
339
+ let foo = Ok("foo");
340
+ return foo.map$0_or_else(|| 42, |v| v.len());
341
+ }
342
+ "# ,
343
+ r#"
344
+ fn foo() {
345
+ let foo = Ok("foo");
346
+ return foo.map_or(42, |v| v.len());
347
+ }
348
+ "# ,
349
+ )
350
+ }
351
+
297
352
#[ test]
298
353
fn replace_or_else_with_or_not_applicable ( ) {
299
354
check_assist_not_applicable (
0 commit comments