@@ -11,37 +11,45 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
11
11
// Converts an Iterator::for_each function into a for loop.
12
12
//
13
13
// ```
14
+ // # //- /lib.rs crate:core
15
+ // # pub mod iter { pub mod traits { pub mod iterator { pub trait Iterator {} } } }
16
+ // # pub struct SomeIter;
17
+ // # impl self::iter::traits::iterator::Iterator for SomeIter {}
18
+ // # //- /lib.rs crate:main deps:core
19
+ // # use core::SomeIter;
14
20
// fn main() {
15
- // let vec = vec![(1, 2), (2, 3), (3, 4)] ;
16
- // x. iter() .for_each(|(x, y)| {
21
+ // let iter = SomeIter ;
22
+ // iter.for_each$0 (|(x, y)| {
17
23
// println!("x: {}, y: {}", x, y);
18
24
// });
19
25
// }
20
26
// ```
21
27
// ->
22
28
// ```
29
+ // # use core::SomeIter;
23
30
// fn main() {
24
- // let vec = vec![(1, 2), (2, 3), (3, 4)] ;
25
- // for (x, y) in x. iter() {
31
+ // let iter = SomeIter ;
32
+ // for (x, y) in iter {
26
33
// println!("x: {}, y: {}", x, y);
27
34
// }
28
35
// }
29
36
// ```
37
+
30
38
pub ( crate ) fn convert_iter_for_each_to_for ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
31
39
let method = ctx. find_node_at_offset :: < ast:: MethodCallExpr > ( ) ?;
32
- let stmt = method. syntax ( ) . parent ( ) . and_then ( ast:: ExprStmt :: cast) ;
33
40
34
41
let closure = match method. arg_list ( ) ?. args ( ) . next ( ) ? {
35
42
ast:: Expr :: ClosureExpr ( expr) => expr,
36
43
_ => return None ,
37
44
} ;
38
45
39
- let ( method, receiver) = validate_method_call_expr ( & ctx. sema , method) ?;
46
+ let ( method, receiver) = validate_method_call_expr ( ctx, method) ?;
40
47
41
48
let param_list = closure. param_list ( ) ?;
42
49
let param = param_list. params ( ) . next ( ) ?. pat ( ) ?;
43
50
let body = closure. body ( ) ?;
44
51
52
+ let stmt = method. syntax ( ) . parent ( ) . and_then ( ast:: ExprStmt :: cast) ;
45
53
let syntax = stmt. as_ref ( ) . map_or ( method. syntax ( ) , |stmt| stmt. syntax ( ) ) ;
46
54
47
55
acc. add (
@@ -65,13 +73,18 @@ pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContex
65
73
}
66
74
67
75
fn validate_method_call_expr (
68
- sema : & hir :: Semantics < ide_db :: RootDatabase > ,
76
+ ctx : & AssistContext ,
69
77
expr : ast:: MethodCallExpr ,
70
78
) -> Option < ( ast:: Expr , ast:: Expr ) > {
71
- if expr. name_ref ( ) ?. text ( ) != "for_each" {
79
+ let name_ref = expr. name_ref ( ) ?;
80
+ if name_ref. syntax ( ) . text_range ( ) . intersect ( ctx. frange . range ) . is_none ( )
81
+ || name_ref. text ( ) != "for_each"
82
+ {
72
83
return None ;
73
84
}
74
85
86
+ let sema = & ctx. sema ;
87
+
75
88
let receiver = expr. receiver ( ) ?;
76
89
let expr = ast:: Expr :: MethodCallExpr ( expr) ;
77
90
@@ -85,7 +98,7 @@ fn validate_method_call_expr(
85
98
86
99
#[ cfg( test) ]
87
100
mod tests {
88
- use crate :: tests:: { check_assist , check_assist_not_applicable } ;
101
+ use crate :: tests:: { self , check_assist } ;
89
102
90
103
use super :: * ;
91
104
@@ -112,6 +125,16 @@ impl Empty {
112
125
check_assist ( convert_iter_for_each_to_for, before, after) ;
113
126
}
114
127
128
+ fn check_assist_not_applicable ( before : & str ) {
129
+ let before = & format ! (
130
+ "//- /main.rs crate:main deps:core,empty_iter{}{}{}" ,
131
+ before,
132
+ EMPTY_ITER_FIXTURE ,
133
+ FamousDefs :: FIXTURE ,
134
+ ) ;
135
+ tests:: check_assist_not_applicable ( convert_iter_for_each_to_for, before) ;
136
+ }
137
+
115
138
#[ test]
116
139
fn test_for_each_in_method_stmt ( ) {
117
140
check_assist_with_fixtures (
@@ -201,13 +224,24 @@ fn main() {
201
224
"# ,
202
225
)
203
226
}
227
+
204
228
#[ test]
205
229
fn test_for_each_not_applicable ( ) {
206
230
check_assist_not_applicable (
207
- convert_iter_for_each_to_for,
208
231
r#"
209
232
fn main() {
210
- value.$0for_each(|x| println!("{}", x));
233
+ ().$0for_each(|x| println!("{}", x));
234
+ }"# ,
235
+ )
236
+ }
237
+
238
+ #[ test]
239
+ fn test_for_each_not_applicable_invalid_cursor_pos ( ) {
240
+ check_assist_not_applicable (
241
+ r#"
242
+ use empty_iter::*;
243
+ fn main() {
244
+ Empty.iter().for_each(|(x, y)| $0println!("x: {}, y: {}", x, y));
211
245
}"# ,
212
246
)
213
247
}
0 commit comments