aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_expand/src/name.rs1
-rw-r--r--crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs86
2 files changed, 36 insertions, 51 deletions
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index c7609e90d..c94fb580a 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -189,6 +189,7 @@ pub mod known {
189 // Components of known path (function name) 189 // Components of known path (function name)
190 filter_map, 190 filter_map,
191 next, 191 next,
192 iter_mut,
192 // Builtin macros 193 // Builtin macros
193 file, 194 file,
194 column, 195 column,
diff --git a/crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs b/crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs
index f329d435f..9fddf889c 100644
--- a/crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs
+++ b/crates/ide_assists/src/handlers/convert_for_to_iter_for_each.rs
@@ -1,4 +1,5 @@
1use ast::LoopBodyOwner; 1use ast::LoopBodyOwner;
2use hir::known;
2use ide_db::helpers::FamousDefs; 3use ide_db::helpers::FamousDefs;
3use stdx::format_to; 4use stdx::format_to;
4use syntax::{ast, AstNode}; 5use syntax::{ast, AstNode};
@@ -68,28 +69,30 @@ pub(crate) fn convert_for_to_iter_for_each(acc: &mut Assists, ctx: &AssistContex
68fn is_ref_and_impls_iter_method( 69fn is_ref_and_impls_iter_method(
69 sema: &hir::Semantics<ide_db::RootDatabase>, 70 sema: &hir::Semantics<ide_db::RootDatabase>,
70 iterable: &ast::Expr, 71 iterable: &ast::Expr,
71) -> Option<(ast::Expr, &'static str)> { 72) -> Option<(ast::Expr, hir::Name)> {
72 let ref_expr = match iterable { 73 let ref_expr = match iterable {
73 ast::Expr::RefExpr(r) => r, 74 ast::Expr::RefExpr(r) => r,
74 _ => return None, 75 _ => return None,
75 }; 76 };
76 let wanted_method = if ref_expr.mut_token().is_some() { "iter_mut" } else { "iter" }; 77 let wanted_method = if ref_expr.mut_token().is_some() { known::iter_mut } else { known::iter };
77 let expr_behind_ref = ref_expr.expr()?; 78 let expr_behind_ref = ref_expr.expr()?;
78 let typ = sema.type_of_expr(&expr_behind_ref)?; 79 let typ = sema.type_of_expr(&expr_behind_ref)?;
79 let scope = sema.scope(iterable.syntax()); 80 let scope = sema.scope(iterable.syntax());
80 let krate = scope.module()?.krate(); 81 let krate = scope.module()?.krate();
81 let traits_in_scope = scope.traits_in_scope(); 82 let traits_in_scope = scope.traits_in_scope();
82 let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?; 83 let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?;
83 let has_wanted_method = 84 let has_wanted_method = typ.iterate_method_candidates(
84 typ.iterate_method_candidates(sema.db, krate, &traits_in_scope, None, |_, func| { 85 sema.db,
85 if func.name(sema.db).to_string() != wanted_method { 86 krate,
86 return None; 87 &traits_in_scope,
87 } 88 Some(&wanted_method),
89 |_, func| {
88 if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) { 90 if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) {
89 return Some(()); 91 return Some(());
90 } 92 }
91 None 93 None
92 }); 94 },
95 );
93 has_wanted_method.and(Some((expr_behind_ref, wanted_method))) 96 has_wanted_method.and(Some((expr_behind_ref, wanted_method)))
94} 97}
95 98
@@ -135,6 +138,16 @@ impl Empty {
135pub struct NoIterMethod; 138pub struct NoIterMethod;
136"; 139";
137 140
141 fn check_assist_with_fixtures(before: &str, after: &str) {
142 let before = &format!(
143 "//- /main.rs crate:main deps:core,empty_iter{}{}{}",
144 before,
145 FamousDefs::FIXTURE,
146 EMPTY_ITER_FIXTURE
147 );
148 check_assist(convert_for_to_iter_for_each, before, after);
149 }
150
138 #[test] 151 #[test]
139 fn test_not_for() { 152 fn test_not_for() {
140 check_assist_not_applicable( 153 check_assist_not_applicable(
@@ -169,7 +182,8 @@ fn main() {
169 182
170 #[test] 183 #[test]
171 fn test_for_borrowed() { 184 fn test_for_borrowed() {
172 let before = r" 185 check_assist_with_fixtures(
186 r"
173use empty_iter::*; 187use empty_iter::*;
174fn main() { 188fn main() {
175 let x = Empty; 189 let x = Empty;
@@ -177,16 +191,7 @@ fn main() {
177 let a = v * 2; 191 let a = v * 2;
178 } 192 }
179} 193}
180"; 194",
181 let before = &format!(
182 "//- /main.rs crate:main deps:core,empty_iter{}{}{}",
183 before,
184 FamousDefs::FIXTURE,
185 EMPTY_ITER_FIXTURE
186 );
187 check_assist(
188 convert_for_to_iter_for_each,
189 before,
190 r" 195 r"
191use empty_iter::*; 196use empty_iter::*;
192fn main() { 197fn main() {
@@ -201,7 +206,8 @@ fn main() {
201 206
202 #[test] 207 #[test]
203 fn test_for_borrowed_no_iter_method() { 208 fn test_for_borrowed_no_iter_method() {
204 let before = r" 209 check_assist_with_fixtures(
210 r"
205use empty_iter::*; 211use empty_iter::*;
206fn main() { 212fn main() {
207 let x = NoIterMethod; 213 let x = NoIterMethod;
@@ -209,16 +215,7 @@ fn main() {
209 let a = v * 2; 215 let a = v * 2;
210 } 216 }
211} 217}
212"; 218",
213 let before = &format!(
214 "//- /main.rs crate:main deps:core,empty_iter{}{}{}",
215 before,
216 FamousDefs::FIXTURE,
217 EMPTY_ITER_FIXTURE
218 );
219 check_assist(
220 convert_for_to_iter_for_each,
221 before,
222 r" 219 r"
223use empty_iter::*; 220use empty_iter::*;
224fn main() { 221fn main() {
@@ -233,7 +230,8 @@ fn main() {
233 230
234 #[test] 231 #[test]
235 fn test_for_borrowed_mut() { 232 fn test_for_borrowed_mut() {
236 let before = r" 233 check_assist_with_fixtures(
234 r"
237use empty_iter::*; 235use empty_iter::*;
238fn main() { 236fn main() {
239 let x = Empty; 237 let x = Empty;
@@ -241,16 +239,7 @@ fn main() {
241 let a = v * 2; 239 let a = v * 2;
242 } 240 }
243} 241}
244"; 242",
245 let before = &format!(
246 "//- /main.rs crate:main deps:core,empty_iter{}{}{}",
247 before,
248 FamousDefs::FIXTURE,
249 EMPTY_ITER_FIXTURE
250 );
251 check_assist(
252 convert_for_to_iter_for_each,
253 before,
254 r" 243 r"
255use empty_iter::*; 244use empty_iter::*;
256fn main() { 245fn main() {
@@ -288,7 +277,8 @@ fn main() {
288 277
289 #[test] 278 #[test]
290 fn test_already_impls_iterator() { 279 fn test_already_impls_iterator() {
291 let before = r#" 280 check_assist_with_fixtures(
281 r#"
292use empty_iter::*; 282use empty_iter::*;
293fn main() { 283fn main() {
294 let x = Empty; 284 let x = Empty;
@@ -296,8 +286,8 @@ fn main() {
296 println!("{}", a); 286 println!("{}", a);
297 } 287 }
298} 288}
299"#; 289"#,
300 let after = r#" 290 r#"
301use empty_iter::*; 291use empty_iter::*;
302fn main() { 292fn main() {
303 let x = Empty; 293 let x = Empty;
@@ -305,13 +295,7 @@ fn main() {
305 println!("{}", a); 295 println!("{}", a);
306 }); 296 });
307} 297}
308"#; 298"#,
309 let before = &format!(
310 "//- /main.rs crate:main deps:core,empty_iter{}{}{}",
311 before,
312 FamousDefs::FIXTURE,
313 EMPTY_ITER_FIXTURE
314 ); 299 );
315 check_assist(convert_for_to_iter_for_each, before, after);
316 } 300 }
317} 301}