diff options
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 47 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 16 | ||||
-rw-r--r-- | crates/ide/src/inlay_hints.rs | 31 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs | 121 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/fill_match_arms.rs | 34 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/generate_deref.rs | 27 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/move_module_to_file.rs | 65 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs | 173 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/famous_defs_fixture.rs | 94 | ||||
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 8 | ||||
-rw-r--r-- | crates/test_utils/src/fixture.rs | 2 | ||||
-rw-r--r-- | crates/test_utils/src/minicore.rs | 101 |
12 files changed, 344 insertions, 375 deletions
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 1edec1615..e0ad41fb9 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -418,48 +418,17 @@ fn issue_2705() { | |||
418 | fn issue_2683_chars_impl() { | 418 | fn issue_2683_chars_impl() { |
419 | check_types( | 419 | check_types( |
420 | r#" | 420 | r#" |
421 | //- /main.rs crate:main deps:std | 421 | //- minicore: iterator |
422 | pub struct Chars<'a> {} | ||
423 | impl<'a> Iterator for Chars<'a> { | ||
424 | type Item = char; | ||
425 | fn next(&mut self) -> Option<char> {} | ||
426 | } | ||
427 | |||
422 | fn test() { | 428 | fn test() { |
423 | let chars: std::str::Chars<'_>; | 429 | let chars: Chars<'_>; |
424 | (chars.next(), chars.nth(1)); | 430 | (chars.next(), chars.nth(1)); |
425 | } //^ (Option<char>, Option<char>) | 431 | } //^ (Option<char>, Option<char>) |
426 | |||
427 | //- /std.rs crate:std | ||
428 | #[prelude_import] | ||
429 | use self::prelude::rust_2018::*; | ||
430 | pub mod prelude { | ||
431 | pub mod rust_2018 { | ||
432 | pub use crate::iter::Iterator; | ||
433 | pub use crate::option::Option; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | pub mod iter { | ||
438 | pub use self::traits::Iterator; | ||
439 | pub mod traits { | ||
440 | pub use self::iterator::Iterator; | ||
441 | |||
442 | pub mod iterator { | ||
443 | pub trait Iterator { | ||
444 | type Item; | ||
445 | fn next(&mut self) -> Option<Self::Item>; | ||
446 | fn nth(&mut self, n: usize) -> Option<Self::Item> {} | ||
447 | } | ||
448 | } | ||
449 | } | ||
450 | } | ||
451 | |||
452 | pub mod option { | ||
453 | pub enum Option<T> {} | ||
454 | } | ||
455 | |||
456 | pub mod str { | ||
457 | pub struct Chars<'a> {} | ||
458 | impl<'a> Iterator for Chars<'a> { | ||
459 | type Item = char; | ||
460 | fn next(&mut self) -> Option<char> {} | ||
461 | } | ||
462 | } | ||
463 | "#, | 432 | "#, |
464 | ); | 433 | ); |
465 | } | 434 | } |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 065cca74f..22e0bfc49 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -1492,7 +1492,7 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { | |||
1492 | fn impl_trait_assoc_binding_projection_bug() { | 1492 | fn impl_trait_assoc_binding_projection_bug() { |
1493 | check_types( | 1493 | check_types( |
1494 | r#" | 1494 | r#" |
1495 | //- /main.rs crate:main deps:std | 1495 | //- minicore: iterator |
1496 | pub trait Language { | 1496 | pub trait Language { |
1497 | type Kind; | 1497 | type Kind; |
1498 | } | 1498 | } |
@@ -1512,20 +1512,6 @@ fn api_walkthrough() { | |||
1512 | node.clone(); | 1512 | node.clone(); |
1513 | } //^ {unknown} | 1513 | } //^ {unknown} |
1514 | } | 1514 | } |
1515 | |||
1516 | //- /std.rs crate:std | ||
1517 | #[prelude_import] use iter::*; | ||
1518 | mod iter { | ||
1519 | trait IntoIterator { | ||
1520 | type Item; | ||
1521 | } | ||
1522 | trait Iterator { | ||
1523 | type Item; | ||
1524 | } | ||
1525 | impl<T: Iterator> IntoIterator for T { | ||
1526 | type Item = <T as Iterator>::Item; | ||
1527 | } | ||
1528 | } | ||
1529 | "#, | 1515 | "#, |
1530 | ); | 1516 | ); |
1531 | } | 1517 | } |
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 9cd33d0e4..335d57a0d 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -434,7 +434,6 @@ fn get_callable( | |||
434 | #[cfg(test)] | 434 | #[cfg(test)] |
435 | mod tests { | 435 | mod tests { |
436 | use expect_test::{expect, Expect}; | 436 | use expect_test::{expect, Expect}; |
437 | use ide_db::helpers::FamousDefs; | ||
438 | use test_utils::extract_annotations; | 437 | use test_utils::extract_annotations; |
439 | 438 | ||
440 | use crate::{fixture, inlay_hints::InlayHintsConfig}; | 439 | use crate::{fixture, inlay_hints::InlayHintsConfig}; |
@@ -487,8 +486,6 @@ mod tests { | |||
487 | } | 486 | } |
488 | 487 | ||
489 | fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { | 488 | fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { |
490 | let ra_fixture = | ||
491 | format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE); | ||
492 | let (analysis, file_id) = fixture::file(&ra_fixture); | 489 | let (analysis, file_id) = fixture::file(&ra_fixture); |
493 | let expected = extract_annotations(&*analysis.file_text(file_id).unwrap()); | 490 | let expected = extract_annotations(&*analysis.file_text(file_id).unwrap()); |
494 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); | 491 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); |
@@ -498,8 +495,6 @@ mod tests { | |||
498 | } | 495 | } |
499 | 496 | ||
500 | fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { | 497 | fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { |
501 | let ra_fixture = | ||
502 | format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE); | ||
503 | let (analysis, file_id) = fixture::file(&ra_fixture); | 498 | let (analysis, file_id) = fixture::file(&ra_fixture); |
504 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); | 499 | let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); |
505 | expect.assert_debug_eq(&inlay_hints) | 500 | expect.assert_debug_eq(&inlay_hints) |
@@ -823,6 +818,7 @@ fn main() { | |||
823 | fn shorten_iterators_in_associated_params() { | 818 | fn shorten_iterators_in_associated_params() { |
824 | check_types( | 819 | check_types( |
825 | r#" | 820 | r#" |
821 | //- minicore: iterators | ||
826 | use core::iter; | 822 | use core::iter; |
827 | 823 | ||
828 | pub struct SomeIter<T> {} | 824 | pub struct SomeIter<T> {} |
@@ -875,7 +871,7 @@ fn main() { | |||
875 | fn fn_hints() { | 871 | fn fn_hints() { |
876 | check_types( | 872 | check_types( |
877 | r#" | 873 | r#" |
878 | trait Sized {} | 874 | //- minicore: fn, sized |
879 | 875 | ||
880 | fn foo() -> impl Fn() { loop {} } | 876 | fn foo() -> impl Fn() { loop {} } |
881 | fn foo1() -> impl Fn(f64) { loop {} } | 877 | fn foo1() -> impl Fn(f64) { loop {} } |
@@ -1073,6 +1069,7 @@ fn main() { | |||
1073 | fn complete_for_hint() { | 1069 | fn complete_for_hint() { |
1074 | check_types( | 1070 | check_types( |
1075 | r#" | 1071 | r#" |
1072 | //- minicore: iterator | ||
1076 | pub struct Vec<T> {} | 1073 | pub struct Vec<T> {} |
1077 | 1074 | ||
1078 | impl<T> Vec<T> { | 1075 | impl<T> Vec<T> { |
@@ -1129,6 +1126,7 @@ fn main() { | |||
1129 | fn shorten_iterator_hints() { | 1126 | fn shorten_iterator_hints() { |
1130 | check_types( | 1127 | check_types( |
1131 | r#" | 1128 | r#" |
1129 | //- minicore: iterators | ||
1132 | use core::iter; | 1130 | use core::iter; |
1133 | 1131 | ||
1134 | struct MyIter; | 1132 | struct MyIter; |
@@ -1230,12 +1228,12 @@ fn main() { | |||
1230 | expect![[r#" | 1228 | expect![[r#" |
1231 | [ | 1229 | [ |
1232 | InlayHint { | 1230 | InlayHint { |
1233 | range: 148..173, | 1231 | range: 147..172, |
1234 | kind: ChainingHint, | 1232 | kind: ChainingHint, |
1235 | label: "B", | 1233 | label: "B", |
1236 | }, | 1234 | }, |
1237 | InlayHint { | 1235 | InlayHint { |
1238 | range: 148..155, | 1236 | range: 147..154, |
1239 | kind: ChainingHint, | 1237 | kind: ChainingHint, |
1240 | label: "A", | 1238 | label: "A", |
1241 | }, | 1239 | }, |
@@ -1290,12 +1288,12 @@ fn main() { | |||
1290 | expect![[r#" | 1288 | expect![[r#" |
1291 | [ | 1289 | [ |
1292 | InlayHint { | 1290 | InlayHint { |
1293 | range: 144..191, | 1291 | range: 143..190, |
1294 | kind: ChainingHint, | 1292 | kind: ChainingHint, |
1295 | label: "C", | 1293 | label: "C", |
1296 | }, | 1294 | }, |
1297 | InlayHint { | 1295 | InlayHint { |
1298 | range: 144..180, | 1296 | range: 143..179, |
1299 | kind: ChainingHint, | 1297 | kind: ChainingHint, |
1300 | label: "B", | 1298 | label: "B", |
1301 | }, | 1299 | }, |
@@ -1335,12 +1333,12 @@ fn main() { | |||
1335 | expect![[r#" | 1333 | expect![[r#" |
1336 | [ | 1334 | [ |
1337 | InlayHint { | 1335 | InlayHint { |
1338 | range: 247..284, | 1336 | range: 246..283, |
1339 | kind: ChainingHint, | 1337 | kind: ChainingHint, |
1340 | label: "B<X<i32, bool>>", | 1338 | label: "B<X<i32, bool>>", |
1341 | }, | 1339 | }, |
1342 | InlayHint { | 1340 | InlayHint { |
1343 | range: 247..266, | 1341 | range: 246..265, |
1344 | kind: ChainingHint, | 1342 | kind: ChainingHint, |
1345 | label: "A<X<i32, bool>>", | 1343 | label: "A<X<i32, bool>>", |
1346 | }, | 1344 | }, |
@@ -1359,6 +1357,7 @@ fn main() { | |||
1359 | max_length: None, | 1357 | max_length: None, |
1360 | }, | 1358 | }, |
1361 | r#" | 1359 | r#" |
1360 | //- minicore: iterators | ||
1362 | use core::iter; | 1361 | use core::iter; |
1363 | 1362 | ||
1364 | struct MyIter; | 1363 | struct MyIter; |
@@ -1381,22 +1380,22 @@ fn main() { | |||
1381 | expect![[r#" | 1380 | expect![[r#" |
1382 | [ | 1381 | [ |
1383 | InlayHint { | 1382 | InlayHint { |
1384 | range: 175..242, | 1383 | range: 174..241, |
1385 | kind: ChainingHint, | 1384 | kind: ChainingHint, |
1386 | label: "impl Iterator<Item = ()>", | 1385 | label: "impl Iterator<Item = ()>", |
1387 | }, | 1386 | }, |
1388 | InlayHint { | 1387 | InlayHint { |
1389 | range: 175..225, | 1388 | range: 174..224, |
1390 | kind: ChainingHint, | 1389 | kind: ChainingHint, |
1391 | label: "impl Iterator<Item = ()>", | 1390 | label: "impl Iterator<Item = ()>", |
1392 | }, | 1391 | }, |
1393 | InlayHint { | 1392 | InlayHint { |
1394 | range: 175..207, | 1393 | range: 174..206, |
1395 | kind: ChainingHint, | 1394 | kind: ChainingHint, |
1396 | label: "impl Iterator<Item = ()>", | 1395 | label: "impl Iterator<Item = ()>", |
1397 | }, | 1396 | }, |
1398 | InlayHint { | 1397 | InlayHint { |
1399 | range: 175..190, | 1398 | range: 174..189, |
1400 | kind: ChainingHint, | 1399 | kind: ChainingHint, |
1401 | label: "&mut MyIter", | 1400 | label: "&mut MyIter", |
1402 | }, | 1401 | }, |
diff --git a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs index 4e75a7b14..7fd73d4c7 100644 --- a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs | |||
@@ -77,9 +77,11 @@ fn validate_method_call_expr( | |||
77 | expr: ast::MethodCallExpr, | 77 | expr: ast::MethodCallExpr, |
78 | ) -> Option<(ast::Expr, ast::Expr)> { | 78 | ) -> Option<(ast::Expr, ast::Expr)> { |
79 | let name_ref = expr.name_ref()?; | 79 | let name_ref = expr.name_ref()?; |
80 | if name_ref.syntax().text_range().intersect(ctx.frange.range).is_none() | 80 | if name_ref.syntax().text_range().intersect(ctx.frange.range).is_none() { |
81 | || name_ref.text() != "for_each" | 81 | cov_mark::hit!(test_for_each_not_applicable_invalid_cursor_pos); |
82 | { | 82 | return None; |
83 | } | ||
84 | if name_ref.text() != "for_each" { | ||
83 | return None; | 85 | return None; |
84 | } | 86 | } |
85 | 87 | ||
@@ -98,59 +100,27 @@ fn validate_method_call_expr( | |||
98 | 100 | ||
99 | #[cfg(test)] | 101 | #[cfg(test)] |
100 | mod tests { | 102 | mod tests { |
101 | use crate::tests::{self, check_assist}; | 103 | use crate::tests::{check_assist, check_assist_not_applicable}; |
102 | 104 | ||
103 | use super::*; | 105 | use super::*; |
104 | 106 | ||
105 | const EMPTY_ITER_FIXTURE: &'static str = r" | ||
106 | //- /lib.rs deps:core crate:empty_iter | ||
107 | pub struct EmptyIter; | ||
108 | impl Iterator for EmptyIter { | ||
109 | type Item = usize; | ||
110 | fn next(&mut self) -> Option<Self::Item> { None } | ||
111 | } | ||
112 | pub struct Empty; | ||
113 | impl Empty { | ||
114 | pub fn iter(&self) -> EmptyIter { EmptyIter } | ||
115 | } | ||
116 | "; | ||
117 | |||
118 | fn check_assist_with_fixtures(before: &str, after: &str) { | ||
119 | let before = &format!( | ||
120 | "//- /main.rs crate:main deps:core,empty_iter{}{}{}", | ||
121 | before, | ||
122 | EMPTY_ITER_FIXTURE, | ||
123 | FamousDefs::FIXTURE, | ||
124 | ); | ||
125 | check_assist(convert_iter_for_each_to_for, before, after); | ||
126 | } | ||
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 | |||
138 | #[test] | 107 | #[test] |
139 | fn test_for_each_in_method_stmt() { | 108 | fn test_for_each_in_method_stmt() { |
140 | check_assist_with_fixtures( | 109 | check_assist( |
110 | convert_iter_for_each_to_for, | ||
141 | r#" | 111 | r#" |
142 | use empty_iter::*; | 112 | //- minicore: iterators |
143 | fn main() { | 113 | fn main() { |
144 | let x = Empty; | 114 | let it = core::iter::repeat(92); |
145 | x.iter().$0for_each(|(x, y)| { | 115 | it.$0for_each(|(x, y)| { |
146 | println!("x: {}, y: {}", x, y); | 116 | println!("x: {}, y: {}", x, y); |
147 | }); | 117 | }); |
148 | }"#, | 118 | } |
119 | "#, | ||
149 | r#" | 120 | r#" |
150 | use empty_iter::*; | ||
151 | fn main() { | 121 | fn main() { |
152 | let x = Empty; | 122 | let it = core::iter::repeat(92); |
153 | for (x, y) in x.iter() { | 123 | for (x, y) in it { |
154 | println!("x: {}, y: {}", x, y); | 124 | println!("x: {}, y: {}", x, y); |
155 | } | 125 | } |
156 | } | 126 | } |
@@ -160,43 +130,21 @@ fn main() { | |||
160 | 130 | ||
161 | #[test] | 131 | #[test] |
162 | fn test_for_each_in_method() { | 132 | fn test_for_each_in_method() { |
163 | check_assist_with_fixtures( | 133 | check_assist( |
134 | convert_iter_for_each_to_for, | ||
164 | r#" | 135 | r#" |
165 | use empty_iter::*; | 136 | //- minicore: iterators |
166 | fn main() { | 137 | fn main() { |
167 | let x = Empty; | 138 | let it = core::iter::repeat(92); |
168 | x.iter().$0for_each(|(x, y)| { | 139 | it.$0for_each(|(x, y)| { |
169 | println!("x: {}, y: {}", x, y); | 140 | println!("x: {}, y: {}", x, y); |
170 | }) | 141 | }) |
171 | }"#, | ||
172 | r#" | ||
173 | use empty_iter::*; | ||
174 | fn main() { | ||
175 | let x = Empty; | ||
176 | for (x, y) in x.iter() { | ||
177 | println!("x: {}, y: {}", x, y); | ||
178 | } | ||
179 | } | 142 | } |
180 | "#, | 143 | "#, |
181 | ) | ||
182 | } | ||
183 | |||
184 | #[test] | ||
185 | fn test_for_each_in_iter_stmt() { | ||
186 | check_assist_with_fixtures( | ||
187 | r#" | ||
188 | use empty_iter::*; | ||
189 | fn main() { | ||
190 | let x = Empty.iter(); | ||
191 | x.$0for_each(|(x, y)| { | ||
192 | println!("x: {}, y: {}", x, y); | ||
193 | }); | ||
194 | }"#, | ||
195 | r#" | 144 | r#" |
196 | use empty_iter::*; | ||
197 | fn main() { | 145 | fn main() { |
198 | let x = Empty.iter(); | 146 | let it = core::iter::repeat(92); |
199 | for (x, y) in x { | 147 | for (x, y) in it { |
200 | println!("x: {}, y: {}", x, y); | 148 | println!("x: {}, y: {}", x, y); |
201 | } | 149 | } |
202 | } | 150 | } |
@@ -206,18 +154,19 @@ fn main() { | |||
206 | 154 | ||
207 | #[test] | 155 | #[test] |
208 | fn test_for_each_without_braces_stmt() { | 156 | fn test_for_each_without_braces_stmt() { |
209 | check_assist_with_fixtures( | 157 | check_assist( |
158 | convert_iter_for_each_to_for, | ||
210 | r#" | 159 | r#" |
211 | use empty_iter::*; | 160 | //- minicore: iterators |
212 | fn main() { | 161 | fn main() { |
213 | let x = Empty; | 162 | let it = core::iter::repeat(92); |
214 | x.iter().$0for_each(|(x, y)| println!("x: {}, y: {}", x, y)); | 163 | it.$0for_each(|(x, y)| println!("x: {}, y: {}", x, y)); |
215 | }"#, | 164 | } |
165 | "#, | ||
216 | r#" | 166 | r#" |
217 | use empty_iter::*; | ||
218 | fn main() { | 167 | fn main() { |
219 | let x = Empty; | 168 | let it = core::iter::repeat(92); |
220 | for (x, y) in x.iter() { | 169 | for (x, y) in it { |
221 | println!("x: {}, y: {}", x, y) | 170 | println!("x: {}, y: {}", x, y) |
222 | } | 171 | } |
223 | } | 172 | } |
@@ -228,7 +177,9 @@ fn main() { | |||
228 | #[test] | 177 | #[test] |
229 | fn test_for_each_not_applicable() { | 178 | fn test_for_each_not_applicable() { |
230 | check_assist_not_applicable( | 179 | check_assist_not_applicable( |
180 | convert_iter_for_each_to_for, | ||
231 | r#" | 181 | r#" |
182 | //- minicore: iterators | ||
232 | fn main() { | 183 | fn main() { |
233 | ().$0for_each(|x| println!("{}", x)); | 184 | ().$0for_each(|x| println!("{}", x)); |
234 | }"#, | 185 | }"#, |
@@ -237,11 +188,13 @@ fn main() { | |||
237 | 188 | ||
238 | #[test] | 189 | #[test] |
239 | fn test_for_each_not_applicable_invalid_cursor_pos() { | 190 | fn test_for_each_not_applicable_invalid_cursor_pos() { |
191 | cov_mark::check!(test_for_each_not_applicable_invalid_cursor_pos); | ||
240 | check_assist_not_applicable( | 192 | check_assist_not_applicable( |
193 | convert_iter_for_each_to_for, | ||
241 | r#" | 194 | r#" |
242 | use empty_iter::*; | 195 | //- minicore: iterators |
243 | fn main() { | 196 | fn main() { |
244 | Empty.iter().for_each(|(x, y)| $0println!("x: {}, y: {}", x, y)); | 197 | core::iter::repeat(92).for_each(|(x, y)| $0println!("x: {}, y: {}", x, y)); |
245 | }"#, | 198 | }"#, |
246 | ) | 199 | ) |
247 | } | 200 | } |
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs index 5a43bdd6f..cd0f6dba9 100644 --- a/crates/ide_assists/src/handlers/fill_match_arms.rs +++ b/crates/ide_assists/src/handlers/fill_match_arms.rs | |||
@@ -278,8 +278,6 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: ExtendedVariant) -> Op | |||
278 | 278 | ||
279 | #[cfg(test)] | 279 | #[cfg(test)] |
280 | mod tests { | 280 | mod tests { |
281 | use ide_db::helpers::FamousDefs; | ||
282 | |||
283 | use crate::tests::{ | 281 | use crate::tests::{ |
284 | check_assist, check_assist_not_applicable, check_assist_target, check_assist_unresolved, | 282 | check_assist, check_assist_not_applicable, check_assist_target, check_assist_unresolved, |
285 | }; | 283 | }; |
@@ -716,7 +714,10 @@ fn main() { | |||
716 | 714 | ||
717 | #[test] | 715 | #[test] |
718 | fn fill_match_arms_tuple_of_enum_partial_with_wildcards() { | 716 | fn fill_match_arms_tuple_of_enum_partial_with_wildcards() { |
719 | let ra_fixture = r#" | 717 | check_assist( |
718 | fill_match_arms, | ||
719 | r#" | ||
720 | //- minicore: option | ||
720 | fn main() { | 721 | fn main() { |
721 | let a = Some(1); | 722 | let a = Some(1); |
722 | let b = Some(()); | 723 | let b = Some(()); |
@@ -725,10 +726,7 @@ fn main() { | |||
725 | (None, Some(_)) => {} | 726 | (None, Some(_)) => {} |
726 | } | 727 | } |
727 | } | 728 | } |
728 | "#; | 729 | "#, |
729 | check_assist( | ||
730 | fill_match_arms, | ||
731 | &format!("//- /main.rs crate:main deps:core{}{}", ra_fixture, FamousDefs::FIXTURE), | ||
732 | r#" | 730 | r#" |
733 | fn main() { | 731 | fn main() { |
734 | let a = Some(1); | 732 | let a = Some(1); |
@@ -746,17 +744,17 @@ fn main() { | |||
746 | #[test] | 744 | #[test] |
747 | fn fill_match_arms_partial_with_deep_pattern() { | 745 | fn fill_match_arms_partial_with_deep_pattern() { |
748 | // Fixme: cannot handle deep patterns | 746 | // Fixme: cannot handle deep patterns |
749 | let ra_fixture = r#" | 747 | check_assist_not_applicable( |
748 | fill_match_arms, | ||
749 | r#" | ||
750 | //- minicore: option | ||
750 | fn main() { | 751 | fn main() { |
751 | match $0Some(true) { | 752 | match $0Some(true) { |
752 | Some(true) => {} | 753 | Some(true) => {} |
753 | None => {} | 754 | None => {} |
754 | } | 755 | } |
755 | } | 756 | } |
756 | "#; | 757 | "#, |
757 | check_assist_not_applicable( | ||
758 | fill_match_arms, | ||
759 | &format!("//- /main.rs crate:main deps:core{}{}", ra_fixture, FamousDefs::FIXTURE), | ||
760 | ); | 758 | ); |
761 | } | 759 | } |
762 | 760 | ||
@@ -1007,17 +1005,15 @@ fn foo(a: A) { | |||
1007 | #[test] | 1005 | #[test] |
1008 | fn option_order() { | 1006 | fn option_order() { |
1009 | cov_mark::check!(option_order); | 1007 | cov_mark::check!(option_order); |
1010 | let before = r#" | 1008 | check_assist( |
1009 | fill_match_arms, | ||
1010 | r#" | ||
1011 | //- minicore: option | ||
1011 | fn foo(opt: Option<i32>) { | 1012 | fn foo(opt: Option<i32>) { |
1012 | match opt$0 { | 1013 | match opt$0 { |
1013 | } | 1014 | } |
1014 | } | 1015 | } |
1015 | "#; | 1016 | "#, |
1016 | let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE); | ||
1017 | |||
1018 | check_assist( | ||
1019 | fill_match_arms, | ||
1020 | before, | ||
1021 | r#" | 1017 | r#" |
1022 | fn foo(opt: Option<i32>) { | 1018 | fn foo(opt: Option<i32>) { |
1023 | match opt { | 1019 | match opt { |
diff --git a/crates/ide_assists/src/handlers/generate_deref.rs b/crates/ide_assists/src/handlers/generate_deref.rs index 4998ff7a4..4e10fdb85 100644 --- a/crates/ide_assists/src/handlers/generate_deref.rs +++ b/crates/ide_assists/src/handlers/generate_deref.rs | |||
@@ -182,23 +182,17 @@ impl std::ops::Deref for B { | |||
182 | ); | 182 | ); |
183 | } | 183 | } |
184 | 184 | ||
185 | fn check_not_applicable(ra_fixture: &str) { | ||
186 | let fixture = format!( | ||
187 | "//- /main.rs crate:main deps:core,std\n{}\n{}", | ||
188 | ra_fixture, | ||
189 | FamousDefs::FIXTURE | ||
190 | ); | ||
191 | check_assist_not_applicable(generate_deref, &fixture) | ||
192 | } | ||
193 | |||
194 | #[test] | 185 | #[test] |
195 | fn test_generate_record_deref_not_applicable_if_already_impl() { | 186 | fn test_generate_record_deref_not_applicable_if_already_impl() { |
196 | cov_mark::check!(test_add_record_deref_impl_already_exists); | 187 | cov_mark::check!(test_add_record_deref_impl_already_exists); |
197 | check_not_applicable( | 188 | check_assist_not_applicable( |
198 | r#"struct A { } | 189 | generate_deref, |
190 | r#" | ||
191 | //- minicore: deref | ||
192 | struct A { } | ||
199 | struct B { $0a: A } | 193 | struct B { $0a: A } |
200 | 194 | ||
201 | impl std::ops::Deref for B { | 195 | impl core::ops::Deref for B { |
202 | type Target = A; | 196 | type Target = A; |
203 | 197 | ||
204 | fn deref(&self) -> &Self::Target { | 198 | fn deref(&self) -> &Self::Target { |
@@ -211,11 +205,14 @@ impl std::ops::Deref for B { | |||
211 | #[test] | 205 | #[test] |
212 | fn test_generate_field_deref_not_applicable_if_already_impl() { | 206 | fn test_generate_field_deref_not_applicable_if_already_impl() { |
213 | cov_mark::check!(test_add_field_deref_impl_already_exists); | 207 | cov_mark::check!(test_add_field_deref_impl_already_exists); |
214 | check_not_applicable( | 208 | check_assist_not_applicable( |
215 | r#"struct A { } | 209 | generate_deref, |
210 | r#" | ||
211 | //- minicore: deref | ||
212 | struct A { } | ||
216 | struct B($0A) | 213 | struct B($0A) |
217 | 214 | ||
218 | impl std::ops::Deref for B { | 215 | impl core::ops::Deref for B { |
219 | type Target = A; | 216 | type Target = A; |
220 | 217 | ||
221 | fn deref(&self) -> &Self::Target { | 218 | fn deref(&self) -> &Self::Target { |
diff --git a/crates/ide_assists/src/handlers/move_module_to_file.rs b/crates/ide_assists/src/handlers/move_module_to_file.rs index 93f702c55..cfc54be8d 100644 --- a/crates/ide_assists/src/handlers/move_module_to_file.rs +++ b/crates/ide_assists/src/handlers/move_module_to_file.rs | |||
@@ -1,5 +1,8 @@ | |||
1 | use std::iter; | ||
2 | |||
1 | use ast::edit::IndentLevel; | 3 | use ast::edit::IndentLevel; |
2 | use ide_db::base_db::AnchoredPathBuf; | 4 | use ide_db::base_db::AnchoredPathBuf; |
5 | use itertools::Itertools; | ||
3 | use stdx::format_to; | 6 | use stdx::format_to; |
4 | use syntax::{ | 7 | use syntax::{ |
5 | ast::{self, edit::AstNodeEdit, NameOwner}, | 8 | ast::{self, edit::AstNodeEdit, NameOwner}, |
@@ -34,7 +37,10 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt | |||
34 | 37 | ||
35 | let module_name = module_ast.name()?; | 38 | let module_name = module_ast.name()?; |
36 | 39 | ||
37 | let module_def = ctx.sema.to_def(&module_ast)?; | 40 | // get to the outermost module syntax so we can grab the module of file we are in |
41 | let outermost_mod_decl = | ||
42 | iter::successors(Some(module_ast.clone()), |module| module.parent()).last()?; | ||
43 | let module_def = ctx.sema.to_def(&outermost_mod_decl)?; | ||
38 | let parent_module = module_def.parent(ctx.db())?; | 44 | let parent_module = module_def.parent(ctx.db())?; |
39 | 45 | ||
40 | acc.add( | 46 | acc.add( |
@@ -43,11 +49,19 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt | |||
43 | target, | 49 | target, |
44 | |builder| { | 50 | |builder| { |
45 | let path = { | 51 | let path = { |
46 | let dir = match parent_module.name(ctx.db()) { | 52 | let mut buf = String::from("./"); |
47 | Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name), | 53 | match parent_module.name(ctx.db()) { |
48 | _ => String::new(), | 54 | Some(name) if !parent_module.is_mod_rs(ctx.db()) => { |
49 | }; | 55 | format_to!(buf, "{}/", name) |
50 | format!("./{}{}.rs", dir, module_name) | 56 | } |
57 | _ => (), | ||
58 | } | ||
59 | let segments = iter::successors(Some(module_ast.clone()), |module| module.parent()) | ||
60 | .filter_map(|it| it.name()) | ||
61 | .collect::<Vec<_>>(); | ||
62 | format_to!(buf, "{}", segments.into_iter().rev().format("/")); | ||
63 | format_to!(buf, ".rs"); | ||
64 | buf | ||
51 | }; | 65 | }; |
52 | let contents = { | 66 | let contents = { |
53 | let items = module_items.dedent(IndentLevel(1)).to_string(); | 67 | let items = module_items.dedent(IndentLevel(1)).to_string(); |
@@ -59,14 +73,13 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt | |||
59 | items | 73 | items |
60 | }; | 74 | }; |
61 | 75 | ||
62 | let mut buf = String::new(); | 76 | let buf = format!("mod {};", module_name); |
63 | format_to!(buf, "mod {};", module_name); | ||
64 | 77 | ||
65 | let replacement_start = if let Some(mod_token) = module_ast.mod_token() { | 78 | let replacement_start = match module_ast.mod_token() { |
66 | mod_token.text_range().start() | 79 | Some(mod_token) => mod_token.text_range(), |
67 | } else { | 80 | None => module_ast.syntax().text_range(), |
68 | module_ast.syntax().text_range().start() | 81 | } |
69 | }; | 82 | .start(); |
70 | 83 | ||
71 | builder.replace( | 84 | builder.replace( |
72 | TextRange::new(replacement_start, module_ast.syntax().text_range().end()), | 85 | TextRange::new(replacement_start, module_ast.syntax().text_range().end()), |
@@ -212,4 +225,30 @@ mod tests; | |||
212 | "#, | 225 | "#, |
213 | ); | 226 | ); |
214 | } | 227 | } |
228 | |||
229 | #[test] | ||
230 | fn extract_nested() { | ||
231 | check_assist( | ||
232 | move_module_to_file, | ||
233 | r#" | ||
234 | //- /lib.rs | ||
235 | mod foo; | ||
236 | //- /foo.rs | ||
237 | mod bar { | ||
238 | mod baz { | ||
239 | mod qux$0 {} | ||
240 | } | ||
241 | } | ||
242 | "#, | ||
243 | r#" | ||
244 | //- /foo.rs | ||
245 | mod bar { | ||
246 | mod baz { | ||
247 | mod qux; | ||
248 | } | ||
249 | } | ||
250 | //- /foo/bar/baz/qux.rs | ||
251 | "#, | ||
252 | ); | ||
253 | } | ||
215 | } | 254 | } |
diff --git a/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs b/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs index 50b05ab0b..5f2aa016f 100644 --- a/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs +++ b/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs | |||
@@ -85,38 +85,48 @@ fn is_ref_and_impls_iter_method( | |||
85 | let krate = scope.module()?.krate(); | 85 | let krate = scope.module()?.krate(); |
86 | let traits_in_scope = scope.traits_in_scope(); | 86 | let traits_in_scope = scope.traits_in_scope(); |
87 | let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?; | 87 | let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?; |
88 | let has_wanted_method = typ.iterate_method_candidates( | 88 | |
89 | sema.db, | 89 | let has_wanted_method = typ |
90 | krate, | 90 | .iterate_method_candidates( |
91 | &traits_in_scope, | 91 | sema.db, |
92 | Some(&wanted_method), | 92 | krate, |
93 | |_, func| { | 93 | &traits_in_scope, |
94 | if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) { | 94 | Some(&wanted_method), |
95 | return Some(()); | 95 | |_, func| { |
96 | } | 96 | if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) { |
97 | None | 97 | return Some(()); |
98 | }, | 98 | } |
99 | ); | 99 | None |
100 | has_wanted_method.and(Some((expr_behind_ref, wanted_method))) | 100 | }, |
101 | ) | ||
102 | .is_some(); | ||
103 | if !has_wanted_method { | ||
104 | return None; | ||
105 | } | ||
106 | |||
107 | Some((expr_behind_ref, wanted_method)) | ||
101 | } | 108 | } |
102 | 109 | ||
103 | /// Whether iterable implements core::Iterator | 110 | /// Whether iterable implements core::Iterator |
104 | fn impls_core_iter(sema: &hir::Semantics<ide_db::RootDatabase>, iterable: &ast::Expr) -> bool { | 111 | fn impls_core_iter(sema: &hir::Semantics<ide_db::RootDatabase>, iterable: &ast::Expr) -> bool { |
105 | let it_typ = if let Some(i) = sema.type_of_expr(iterable) { | 112 | let it_typ = match sema.type_of_expr(iterable) { |
106 | i | 113 | Some(it) => it, |
107 | } else { | 114 | None => return false, |
108 | return false; | ||
109 | }; | 115 | }; |
110 | let module = if let Some(m) = sema.scope(iterable.syntax()).module() { | 116 | |
111 | m | 117 | let module = match sema.scope(iterable.syntax()).module() { |
112 | } else { | 118 | Some(it) => it, |
113 | return false; | 119 | None => return false, |
114 | }; | 120 | }; |
121 | |||
115 | let krate = module.krate(); | 122 | let krate = module.krate(); |
116 | if let Some(iter_trait) = FamousDefs(sema, Some(krate)).core_iter_Iterator() { | 123 | match FamousDefs(sema, Some(krate)).core_iter_Iterator() { |
117 | return it_typ.impls_trait(sema.db, iter_trait, &[]); | 124 | Some(iter_trait) => { |
125 | cov_mark::hit!(test_already_impls_iterator); | ||
126 | it_typ.impls_trait(sema.db, iter_trait, &[]) | ||
127 | } | ||
128 | None => false, | ||
118 | } | 129 | } |
119 | false | ||
120 | } | 130 | } |
121 | 131 | ||
122 | #[cfg(test)] | 132 | #[cfg(test)] |
@@ -125,33 +135,6 @@ mod tests { | |||
125 | 135 | ||
126 | use super::*; | 136 | use super::*; |
127 | 137 | ||
128 | const EMPTY_ITER_FIXTURE: &'static str = r" | ||
129 | //- /lib.rs deps:core crate:empty_iter | ||
130 | pub struct EmptyIter; | ||
131 | impl Iterator for EmptyIter { | ||
132 | type Item = usize; | ||
133 | fn next(&mut self) -> Option<Self::Item> { None } | ||
134 | } | ||
135 | |||
136 | pub struct Empty; | ||
137 | impl Empty { | ||
138 | pub fn iter(&self) -> EmptyIter { EmptyIter } | ||
139 | pub fn iter_mut(&self) -> EmptyIter { EmptyIter } | ||
140 | } | ||
141 | |||
142 | pub struct NoIterMethod; | ||
143 | "; | ||
144 | |||
145 | fn check_assist_with_fixtures(before: &str, after: &str) { | ||
146 | let before = &format!( | ||
147 | "//- /main.rs crate:main deps:core,empty_iter{}{}{}", | ||
148 | before, | ||
149 | FamousDefs::FIXTURE, | ||
150 | EMPTY_ITER_FIXTURE | ||
151 | ); | ||
152 | check_assist(replace_for_loop_with_for_each, before, after); | ||
153 | } | ||
154 | |||
155 | #[test] | 138 | #[test] |
156 | fn test_not_for() { | 139 | fn test_not_for() { |
157 | check_assist_not_applicable( | 140 | check_assist_not_applicable( |
@@ -201,33 +184,50 @@ fn main() { | |||
201 | 184 | ||
202 | #[test] | 185 | #[test] |
203 | fn test_for_borrowed() { | 186 | fn test_for_borrowed() { |
204 | check_assist_with_fixtures( | 187 | check_assist( |
205 | r" | 188 | replace_for_loop_with_for_each, |
206 | use empty_iter::*; | 189 | r#" |
190 | //- minicore: iterators | ||
191 | use core::iter::{Repeat, repeat}; | ||
192 | |||
193 | struct S; | ||
194 | impl S { | ||
195 | fn iter(&self) -> Repeat<i32> { repeat(92) } | ||
196 | fn iter_mut(&mut self) -> Repeat<i32> { repeat(92) } | ||
197 | } | ||
198 | |||
207 | fn main() { | 199 | fn main() { |
208 | let x = Empty; | 200 | let x = S; |
209 | for $0v in &x { | 201 | for $0v in &x { |
210 | let a = v * 2; | 202 | let a = v * 2; |
211 | } | 203 | } |
212 | } | 204 | } |
213 | ", | 205 | "#, |
214 | r" | 206 | r#" |
215 | use empty_iter::*; | 207 | use core::iter::{Repeat, repeat}; |
208 | |||
209 | struct S; | ||
210 | impl S { | ||
211 | fn iter(&self) -> Repeat<i32> { repeat(92) } | ||
212 | fn iter_mut(&mut self) -> Repeat<i32> { repeat(92) } | ||
213 | } | ||
214 | |||
216 | fn main() { | 215 | fn main() { |
217 | let x = Empty; | 216 | let x = S; |
218 | x.iter().for_each(|v| { | 217 | x.iter().for_each(|v| { |
219 | let a = v * 2; | 218 | let a = v * 2; |
220 | }); | 219 | }); |
221 | } | 220 | } |
222 | ", | 221 | "#, |
223 | ) | 222 | ) |
224 | } | 223 | } |
225 | 224 | ||
226 | #[test] | 225 | #[test] |
227 | fn test_for_borrowed_no_iter_method() { | 226 | fn test_for_borrowed_no_iter_method() { |
228 | check_assist_with_fixtures( | 227 | check_assist( |
228 | replace_for_loop_with_for_each, | ||
229 | r" | 229 | r" |
230 | use empty_iter::*; | 230 | struct NoIterMethod; |
231 | fn main() { | 231 | fn main() { |
232 | let x = NoIterMethod; | 232 | let x = NoIterMethod; |
233 | for $0v in &x { | 233 | for $0v in &x { |
@@ -236,7 +236,7 @@ fn main() { | |||
236 | } | 236 | } |
237 | ", | 237 | ", |
238 | r" | 238 | r" |
239 | use empty_iter::*; | 239 | struct NoIterMethod; |
240 | fn main() { | 240 | fn main() { |
241 | let x = NoIterMethod; | 241 | let x = NoIterMethod; |
242 | (&x).into_iter().for_each(|v| { | 242 | (&x).into_iter().for_each(|v| { |
@@ -249,25 +249,41 @@ fn main() { | |||
249 | 249 | ||
250 | #[test] | 250 | #[test] |
251 | fn test_for_borrowed_mut() { | 251 | fn test_for_borrowed_mut() { |
252 | check_assist_with_fixtures( | 252 | check_assist( |
253 | r" | 253 | replace_for_loop_with_for_each, |
254 | use empty_iter::*; | 254 | r#" |
255 | //- minicore: iterators | ||
256 | use core::iter::{Repeat, repeat}; | ||
257 | |||
258 | struct S; | ||
259 | impl S { | ||
260 | fn iter(&self) -> Repeat<i32> { repeat(92) } | ||
261 | fn iter_mut(&mut self) -> Repeat<i32> { repeat(92) } | ||
262 | } | ||
263 | |||
255 | fn main() { | 264 | fn main() { |
256 | let x = Empty; | 265 | let x = S; |
257 | for $0v in &mut x { | 266 | for $0v in &mut x { |
258 | let a = v * 2; | 267 | let a = v * 2; |
259 | } | 268 | } |
260 | } | 269 | } |
261 | ", | 270 | "#, |
262 | r" | 271 | r#" |
263 | use empty_iter::*; | 272 | use core::iter::{Repeat, repeat}; |
273 | |||
274 | struct S; | ||
275 | impl S { | ||
276 | fn iter(&self) -> Repeat<i32> { repeat(92) } | ||
277 | fn iter_mut(&mut self) -> Repeat<i32> { repeat(92) } | ||
278 | } | ||
279 | |||
264 | fn main() { | 280 | fn main() { |
265 | let x = Empty; | 281 | let x = S; |
266 | x.iter_mut().for_each(|v| { | 282 | x.iter_mut().for_each(|v| { |
267 | let a = v * 2; | 283 | let a = v * 2; |
268 | }); | 284 | }); |
269 | } | 285 | } |
270 | ", | 286 | "#, |
271 | ) | 287 | ) |
272 | } | 288 | } |
273 | 289 | ||
@@ -296,21 +312,20 @@ fn main() { | |||
296 | 312 | ||
297 | #[test] | 313 | #[test] |
298 | fn test_already_impls_iterator() { | 314 | fn test_already_impls_iterator() { |
299 | check_assist_with_fixtures( | 315 | cov_mark::check!(test_already_impls_iterator); |
316 | check_assist( | ||
317 | replace_for_loop_with_for_each, | ||
300 | r#" | 318 | r#" |
301 | use empty_iter::*; | 319 | //- minicore: iterators |
302 | fn main() { | 320 | fn main() { |
303 | let x = Empty; | 321 | for$0 a in core::iter::repeat(92).take(1) { |
304 | for$0 a in x.iter().take(1) { | ||
305 | println!("{}", a); | 322 | println!("{}", a); |
306 | } | 323 | } |
307 | } | 324 | } |
308 | "#, | 325 | "#, |
309 | r#" | 326 | r#" |
310 | use empty_iter::*; | ||
311 | fn main() { | 327 | fn main() { |
312 | let x = Empty; | 328 | core::iter::repeat(92).take(1).for_each(|a| { |
313 | x.iter().take(1).for_each(|a| { | ||
314 | println!("{}", a); | 329 | println!("{}", a); |
315 | }); | 330 | }); |
316 | } | 331 | } |
diff --git a/crates/ide_db/src/helpers/famous_defs_fixture.rs b/crates/ide_db/src/helpers/famous_defs_fixture.rs index 312851966..551203936 100644 --- a/crates/ide_db/src/helpers/famous_defs_fixture.rs +++ b/crates/ide_db/src/helpers/famous_defs_fixture.rs | |||
@@ -26,100 +26,6 @@ pub mod default { | |||
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | pub mod iter { | ||
30 | pub use self::traits::{collect::IntoIterator, iterator::Iterator}; | ||
31 | mod traits { | ||
32 | pub(crate) mod iterator { | ||
33 | use crate::option::Option; | ||
34 | pub trait Iterator { | ||
35 | type Item; | ||
36 | fn next(&mut self) -> Option<Self::Item>; | ||
37 | fn by_ref(&mut self) -> &mut Self { | ||
38 | self | ||
39 | } | ||
40 | fn take(self, n: usize) -> crate::iter::Take<Self> { | ||
41 | crate::iter::Take { inner: self } | ||
42 | } | ||
43 | } | ||
44 | |||
45 | impl<I: Iterator> Iterator for &mut I { | ||
46 | type Item = I::Item; | ||
47 | fn next(&mut self) -> Option<I::Item> { | ||
48 | (**self).next() | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | pub(crate) mod collect { | ||
53 | pub trait IntoIterator { | ||
54 | type Item; | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
59 | pub use self::sources::*; | ||
60 | pub(crate) mod sources { | ||
61 | use super::Iterator; | ||
62 | use crate::option::Option::{self, *}; | ||
63 | pub struct Repeat<A> { | ||
64 | element: A, | ||
65 | } | ||
66 | |||
67 | pub fn repeat<T>(elt: T) -> Repeat<T> { | ||
68 | Repeat { element: elt } | ||
69 | } | ||
70 | |||
71 | impl<A> Iterator for Repeat<A> { | ||
72 | type Item = A; | ||
73 | |||
74 | fn next(&mut self) -> Option<A> { | ||
75 | None | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | |||
80 | pub use self::adapters::*; | ||
81 | pub(crate) mod adapters { | ||
82 | use super::Iterator; | ||
83 | use crate::option::Option::{self, *}; | ||
84 | pub struct Take<I> { | ||
85 | pub(crate) inner: I, | ||
86 | } | ||
87 | impl<I> Iterator for Take<I> | ||
88 | where | ||
89 | I: Iterator, | ||
90 | { | ||
91 | type Item = <I as Iterator>::Item; | ||
92 | fn next(&mut self) -> Option<<I as Iterator>::Item> { | ||
93 | None | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | |||
99 | pub mod ops { | ||
100 | #[lang = "fn"] | ||
101 | pub trait Fn<Args>: FnMut<Args> { | ||
102 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | ||
103 | } | ||
104 | |||
105 | #[lang = "fn_mut"] | ||
106 | pub trait FnMut<Args>: FnOnce<Args> { | ||
107 | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; | ||
108 | } | ||
109 | #[lang = "fn_once"] | ||
110 | pub trait FnOnce<Args> { | ||
111 | #[lang = "fn_once_output"] | ||
112 | type Output; | ||
113 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
114 | } | ||
115 | |||
116 | #[lang = "deref"] | ||
117 | pub trait Deref { | ||
118 | type Target: ?Sized; | ||
119 | fn deref(&self) -> &Self::Target; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | pub mod option { | 29 | pub mod option { |
124 | pub enum Option<T> { | 30 | pub enum Option<T> { |
125 | None, | 31 | None, |
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 2bd9ad867..b057e6624 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -675,6 +675,14 @@ impl ast::LifetimeParam { | |||
675 | } | 675 | } |
676 | } | 676 | } |
677 | 677 | ||
678 | impl ast::Module { | ||
679 | /// Returns the parent ast::Module, this is different than the semantic parent in that this only | ||
680 | /// considers parent declarations in the AST | ||
681 | pub fn parent(&self) -> Option<ast::Module> { | ||
682 | self.syntax().ancestors().nth(2).and_then(ast::Module::cast) | ||
683 | } | ||
684 | } | ||
685 | |||
678 | impl ast::RangePat { | 686 | impl ast::RangePat { |
679 | pub fn start(&self) -> Option<ast::Pat> { | 687 | pub fn start(&self) -> Option<ast::Pat> { |
680 | self.syntax() | 688 | self.syntax() |
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index 005a5c092..8d8f3b560 100644 --- a/crates/test_utils/src/fixture.rs +++ b/crates/test_utils/src/fixture.rs | |||
@@ -154,7 +154,7 @@ impl Fixture { | |||
154 | let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); | 154 | let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); |
155 | 155 | ||
156 | let path = components[0].to_string(); | 156 | let path = components[0].to_string(); |
157 | assert!(path.starts_with('/')); | 157 | assert!(path.starts_with('/'), "fixture path does not start with `/`: {:?}", path); |
158 | 158 | ||
159 | let mut krate = None; | 159 | let mut krate = None; |
160 | let mut deps = Vec::new(); | 160 | let mut deps = Vec::new(); |
diff --git a/crates/test_utils/src/minicore.rs b/crates/test_utils/src/minicore.rs index e04ca58d2..e6d2301c7 100644 --- a/crates/test_utils/src/minicore.rs +++ b/crates/test_utils/src/minicore.rs | |||
@@ -20,6 +20,8 @@ | |||
20 | //! future: pin | 20 | //! future: pin |
21 | //! option: | 21 | //! option: |
22 | //! result: | 22 | //! result: |
23 | //! iterator: option | ||
24 | //! iterators: iterator | ||
23 | 25 | ||
24 | pub mod marker { | 26 | pub mod marker { |
25 | // region:sized | 27 | // region:sized |
@@ -206,9 +208,108 @@ pub mod task { | |||
206 | } | 208 | } |
207 | // endregion:future | 209 | // endregion:future |
208 | 210 | ||
211 | // region:iterator | ||
212 | pub mod iter { | ||
213 | // region:iterators | ||
214 | mod adapters { | ||
215 | pub struct Take<I> { | ||
216 | iter: I, | ||
217 | n: usize, | ||
218 | } | ||
219 | |||
220 | impl<I> Iterator for Take<I> | ||
221 | where | ||
222 | I: Iterator, | ||
223 | { | ||
224 | type Item = <I as Iterator>::Item; | ||
225 | |||
226 | fn next(&mut self) -> Option<<I as Iterator>::Item> { | ||
227 | loop {} | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | pub use self::adapters::Take; | ||
232 | |||
233 | mod sources { | ||
234 | mod repeat { | ||
235 | pub fn repeat<T>(elt: T) -> Repeat<T> { | ||
236 | loop {} | ||
237 | } | ||
238 | |||
239 | pub struct Repeat<A> { | ||
240 | element: A, | ||
241 | } | ||
242 | |||
243 | impl<A> Iterator for Repeat<A> { | ||
244 | type Item = A; | ||
245 | |||
246 | fn next(&mut self) -> Option<A> { | ||
247 | loop {} | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | pub use self::repeat::{repeat, Repeat}; | ||
252 | } | ||
253 | pub use self::sources::{repeat, Repeat}; | ||
254 | // endregion:iterators | ||
255 | |||
256 | mod traits { | ||
257 | mod iterator { | ||
258 | use super::super::Take; | ||
259 | |||
260 | pub trait Iterator { | ||
261 | type Item; | ||
262 | #[lang = "next"] | ||
263 | fn next(&mut self) -> Option<Self::Item>; | ||
264 | fn nth(&mut self, n: usize) -> Option<Self::Item> { | ||
265 | loop {} | ||
266 | } | ||
267 | fn by_ref(&mut self) -> &mut Self | ||
268 | where | ||
269 | Self: Sized, | ||
270 | { | ||
271 | self | ||
272 | } | ||
273 | // region:iterators | ||
274 | fn take(self, n: usize) -> crate::iter::Take<Self> { | ||
275 | loop {} | ||
276 | } | ||
277 | // endregion:iterators | ||
278 | } | ||
279 | impl<I: Iterator + ?Sized> Iterator for &mut I { | ||
280 | type Item = I::Item; | ||
281 | fn next(&mut self) -> Option<I::Item> { | ||
282 | (**self).next() | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | pub use self::iterator::Iterator; | ||
287 | |||
288 | mod collect { | ||
289 | pub trait IntoIterator { | ||
290 | type Item; | ||
291 | type IntoIter: Iterator<Item = Self::Item>; | ||
292 | #[lang = "into_iter"] | ||
293 | fn into_iter(self) -> Self::IntoIter; | ||
294 | } | ||
295 | impl<I: Iterator> IntoIterator for I { | ||
296 | type Item = I::Item; | ||
297 | type IntoIter = I; | ||
298 | fn into_iter(self) -> I { | ||
299 | self | ||
300 | } | ||
301 | } | ||
302 | } | ||
303 | pub use self::collect::IntoIterator; | ||
304 | } | ||
305 | pub use self::traits::{IntoIterator, Iterator}; | ||
306 | } | ||
307 | // endregion:iterator | ||
308 | |||
209 | pub mod prelude { | 309 | pub mod prelude { |
210 | pub mod v1 { | 310 | pub mod v1 { |
211 | pub use crate::{ | 311 | pub use crate::{ |
312 | iter::{IntoIterator, Iterator}, // :iterator | ||
212 | marker::Sized, // :sized | 313 | marker::Sized, // :sized |
213 | ops::{Fn, FnMut, FnOnce}, // :fn | 314 | ops::{Fn, FnMut, FnOnce}, // :fn |
214 | option::Option::{self, None, Some}, // :option | 315 | option::Option::{self, None, Some}, // :option |