aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists')
-rw-r--r--crates/ide_assists/src/handlers/fix_visibility.rs34
-rw-r--r--crates/ide_assists/src/handlers/generate_function.rs49
-rw-r--r--crates/ide_assists/src/handlers/qualify_path.rs1201
-rw-r--r--crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs5
-rw-r--r--crates/ide_assists/src/lib.rs163
-rw-r--r--crates/ide_assists/src/tests.rs26
6 files changed, 660 insertions, 818 deletions
diff --git a/crates/ide_assists/src/handlers/fix_visibility.rs b/crates/ide_assists/src/handlers/fix_visibility.rs
index 9b432e92f..f834bf16a 100644
--- a/crates/ide_assists/src/handlers/fix_visibility.rs
+++ b/crates/ide_assists/src/handlers/fix_visibility.rs
@@ -361,8 +361,6 @@ pub struct Foo { pub bar: () }
361 } 361 }
362 362
363 #[test] 363 #[test]
364 #[ignore]
365 // FIXME reenable this test when `Semantics::resolve_record_field` works with union fields
366 fn fix_visibility_of_union_field() { 364 fn fix_visibility_of_union_field() {
367 check_assist( 365 check_assist(
368 fix_visibility, 366 fix_visibility,
@@ -583,25 +581,25 @@ pub struct Foo { pub(crate) bar: () }
583 } 581 }
584 582
585 #[test] 583 #[test]
586 #[ignore]
587 // FIXME handle reexports properly
588 fn fix_visibility_of_reexport() { 584 fn fix_visibility_of_reexport() {
585 // FIXME: broken test, this should fix visibility of the re-export
586 // rather than the struct.
589 check_assist( 587 check_assist(
590 fix_visibility, 588 fix_visibility,
591 r" 589 r#"
592 mod foo { 590mod foo {
593 use bar::Baz; 591 use bar::Baz;
594 mod bar { pub(super) struct Baz; } 592 mod bar { pub(super) struct Baz; }
595 } 593}
596 foo::Baz$0 594foo::Baz$0
597 ", 595"#,
598 r" 596 r#"
599 mod foo { 597mod foo {
600 $0pub(crate) use bar::Baz; 598 use bar::Baz;
601 mod bar { pub(super) struct Baz; } 599 mod bar { $0pub(crate) struct Baz; }
602 } 600}
603 foo::Baz 601foo::Baz
604 ", 602"#,
605 ) 603 )
606 } 604 }
607} 605}
diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index 706c995ac..6a658d4cf 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -811,9 +811,8 @@ fn bar(baz: Baz::Bof) ${0:-> ()} {
811 } 811 }
812 812
813 #[test] 813 #[test]
814 #[ignore]
815 // FIXME fix printing the generics of a `Ty` to make this test pass
816 fn add_function_with_generic_arg() { 814 fn add_function_with_generic_arg() {
815 // FIXME: This is wrong, generated `bar` should include generic parameter.
817 check_assist( 816 check_assist(
818 generate_function, 817 generate_function,
819 r" 818 r"
@@ -826,7 +825,7 @@ fn foo<T>(t: T) {
826 bar(t) 825 bar(t)
827} 826}
828 827
829fn bar<T>(t: T) ${0:-> ()} { 828fn bar(t: T) ${0:-> ()} {
830 todo!() 829 todo!()
831} 830}
832", 831",
@@ -834,9 +833,8 @@ fn bar<T>(t: T) ${0:-> ()} {
834 } 833 }
835 834
836 #[test] 835 #[test]
837 #[ignore]
838 // FIXME Fix function type printing to make this test pass
839 fn add_function_with_fn_arg() { 836 fn add_function_with_fn_arg() {
837 // FIXME: The argument in `bar` is wrong.
840 check_assist( 838 check_assist(
841 generate_function, 839 generate_function,
842 r" 840 r"
@@ -857,7 +855,7 @@ fn foo() {
857 bar(Baz::new); 855 bar(Baz::new);
858} 856}
859 857
860fn bar(arg: fn() -> Baz) ${0:-> ()} { 858fn bar(new: fn) ${0:-> ()} {
861 todo!() 859 todo!()
862} 860}
863", 861",
@@ -865,9 +863,8 @@ fn bar(arg: fn() -> Baz) ${0:-> ()} {
865 } 863 }
866 864
867 #[test] 865 #[test]
868 #[ignore]
869 // FIXME Fix closure type printing to make this test pass
870 fn add_function_with_closure_arg() { 866 fn add_function_with_closure_arg() {
867 // FIXME: The argument in `bar` is wrong.
871 check_assist( 868 check_assist(
872 generate_function, 869 generate_function,
873 r" 870 r"
@@ -882,7 +879,7 @@ fn foo() {
882 bar(closure) 879 bar(closure)
883} 880}
884 881
885fn bar(closure: impl Fn(i64) -> i64) ${0:-> ()} { 882fn bar(closure: ()) ${0:-> ()} {
886 todo!() 883 todo!()
887} 884}
888", 885",
@@ -986,13 +983,10 @@ fn foo() {
986 } 983 }
987 984
988 #[test] 985 #[test]
989 #[ignore]
990 // Ignored until local imports are supported.
991 // See https://github.com/rust-analyzer/rust-analyzer/issues/1165
992 fn qualified_path_uses_correct_scope() { 986 fn qualified_path_uses_correct_scope() {
993 check_assist( 987 check_assist(
994 generate_function, 988 generate_function,
995 " 989 r#"
996mod foo { 990mod foo {
997 pub struct Foo; 991 pub struct Foo;
998} 992}
@@ -1001,8 +995,8 @@ fn bar() {
1001 let foo = Foo; 995 let foo = Foo;
1002 baz$0(foo) 996 baz$0(foo)
1003} 997}
1004", 998"#,
1005 " 999 r#"
1006mod foo { 1000mod foo {
1007 pub struct Foo; 1001 pub struct Foo;
1008} 1002}
@@ -1015,7 +1009,7 @@ fn bar() {
1015fn baz(foo: foo::Foo) ${0:-> ()} { 1009fn baz(foo: foo::Foo) ${0:-> ()} {
1016 todo!() 1010 todo!()
1017} 1011}
1018", 1012"#,
1019 ) 1013 )
1020 } 1014 }
1021 1015
@@ -1141,40 +1135,29 @@ fn bar() {}
1141 // The assist is only active if the cursor is on an unresolved path, 1135 // The assist is only active if the cursor is on an unresolved path,
1142 // but the assist should only be offered if the path is a function call. 1136 // but the assist should only be offered if the path is a function call.
1143 generate_function, 1137 generate_function,
1144 r" 1138 r#"
1145fn foo() { 1139fn foo() {
1146 bar(b$0az); 1140 bar(b$0az);
1147} 1141}
1148 1142
1149fn bar(baz: ()) {} 1143fn bar(baz: ()) {}
1150", 1144"#,
1151 ) 1145 )
1152 } 1146 }
1153 1147
1154 #[test] 1148 #[test]
1155 #[ignore]
1156 fn create_method_with_no_args() { 1149 fn create_method_with_no_args() {
1157 check_assist( 1150 // FIXME: This is wrong, this should just work.
1151 check_assist_not_applicable(
1158 generate_function, 1152 generate_function,
1159 r" 1153 r#"
1160struct Foo; 1154struct Foo;
1161impl Foo { 1155impl Foo {
1162 fn foo(&self) { 1156 fn foo(&self) {
1163 self.bar()$0; 1157 self.bar()$0;
1164 } 1158 }
1165} 1159}
1166 ", 1160 "#,
1167 r"
1168struct Foo;
1169impl Foo {
1170 fn foo(&self) {
1171 self.bar();
1172 }
1173 fn bar(&self) {
1174 todo!();
1175 }
1176}
1177 ",
1178 ) 1161 )
1179 } 1162 }
1180} 1163}
diff --git a/crates/ide_assists/src/handlers/qualify_path.rs b/crates/ide_assists/src/handlers/qualify_path.rs
index f91770a76..1d7be183a 100644
--- a/crates/ide_assists/src/handlers/qualify_path.rs
+++ b/crates/ide_assists/src/handlers/qualify_path.rs
@@ -216,28 +216,28 @@ mod tests {
216 cov_mark::check!(qualify_path_unqualified_name); 216 cov_mark::check!(qualify_path_unqualified_name);
217 check_assist( 217 check_assist(
218 qualify_path, 218 qualify_path,
219 r" 219 r#"
220 mod std { 220mod std {
221 pub mod fmt { 221 pub mod fmt {
222 pub struct Formatter; 222 pub struct Formatter;
223 } 223 }
224 } 224}
225 225
226 use std::fmt; 226use std::fmt;
227 227
228 $0Formatter 228$0Formatter
229 ", 229"#,
230 r" 230 r#"
231 mod std { 231mod std {
232 pub mod fmt { 232 pub mod fmt {
233 pub struct Formatter; 233 pub struct Formatter;
234 } 234 }
235 } 235}
236 236
237 use std::fmt; 237use std::fmt;
238 238
239 fmt::Formatter 239fmt::Formatter
240 ", 240"#,
241 ); 241 );
242 } 242 }
243 243
@@ -245,20 +245,20 @@ mod tests {
245 fn applicable_when_found_an_import() { 245 fn applicable_when_found_an_import() {
246 check_assist( 246 check_assist(
247 qualify_path, 247 qualify_path,
248 r" 248 r#"
249 $0PubStruct 249$0PubStruct
250 250
251 pub mod PubMod { 251pub mod PubMod {
252 pub struct PubStruct; 252 pub struct PubStruct;
253 } 253}
254 ", 254"#,
255 r" 255 r#"
256 PubMod::PubStruct 256PubMod::PubStruct
257 257
258 pub mod PubMod { 258pub mod PubMod {
259 pub struct PubStruct; 259 pub struct PubStruct;
260 } 260}
261 ", 261"#,
262 ); 262 );
263 } 263 }
264 264
@@ -266,26 +266,26 @@ mod tests {
266 fn applicable_in_macros() { 266 fn applicable_in_macros() {
267 check_assist( 267 check_assist(
268 qualify_path, 268 qualify_path,
269 r" 269 r#"
270 macro_rules! foo { 270macro_rules! foo {
271 ($i:ident) => { fn foo(a: $i) {} } 271 ($i:ident) => { fn foo(a: $i) {} }
272 } 272}
273 foo!(Pub$0Struct); 273foo!(Pub$0Struct);
274 274
275 pub mod PubMod { 275pub mod PubMod {
276 pub struct PubStruct; 276 pub struct PubStruct;
277 } 277}
278 ", 278"#,
279 r" 279 r#"
280 macro_rules! foo { 280macro_rules! foo {
281 ($i:ident) => { fn foo(a: $i) {} } 281 ($i:ident) => { fn foo(a: $i) {} }
282 } 282}
283 foo!(PubMod::PubStruct); 283foo!(PubMod::PubStruct);
284 284
285 pub mod PubMod { 285pub mod PubMod {
286 pub struct PubStruct; 286 pub struct PubStruct;
287 } 287}
288 ", 288"#,
289 ); 289 );
290 } 290 }
291 291
@@ -293,32 +293,32 @@ mod tests {
293 fn applicable_when_found_multiple_imports() { 293 fn applicable_when_found_multiple_imports() {
294 check_assist( 294 check_assist(
295 qualify_path, 295 qualify_path,
296 r" 296 r#"
297 PubSt$0ruct 297PubSt$0ruct
298 298
299 pub mod PubMod1 { 299pub mod PubMod1 {
300 pub struct PubStruct; 300 pub struct PubStruct;
301 } 301}
302 pub mod PubMod2 { 302pub mod PubMod2 {
303 pub struct PubStruct; 303 pub struct PubStruct;
304 } 304}
305 pub mod PubMod3 { 305pub mod PubMod3 {
306 pub struct PubStruct; 306 pub struct PubStruct;
307 } 307}
308 ", 308"#,
309 r" 309 r#"
310 PubMod3::PubStruct 310PubMod3::PubStruct
311 311
312 pub mod PubMod1 { 312pub mod PubMod1 {
313 pub struct PubStruct; 313 pub struct PubStruct;
314 } 314}
315 pub mod PubMod2 { 315pub mod PubMod2 {
316 pub struct PubStruct; 316 pub struct PubStruct;
317 } 317}
318 pub mod PubMod3 { 318pub mod PubMod3 {
319 pub struct PubStruct; 319 pub struct PubStruct;
320 } 320}
321 ", 321"#,
322 ); 322 );
323 } 323 }
324 324
@@ -326,15 +326,15 @@ mod tests {
326 fn not_applicable_for_already_imported_types() { 326 fn not_applicable_for_already_imported_types() {
327 check_assist_not_applicable( 327 check_assist_not_applicable(
328 qualify_path, 328 qualify_path,
329 r" 329 r#"
330 use PubMod::PubStruct; 330use PubMod::PubStruct;
331 331
332 PubStruct$0 332PubStruct$0
333 333
334 pub mod PubMod { 334pub mod PubMod {
335 pub struct PubStruct; 335 pub struct PubStruct;
336 } 336}
337 ", 337"#,
338 ); 338 );
339 } 339 }
340 340
@@ -342,35 +342,32 @@ mod tests {
342 fn not_applicable_for_types_with_private_paths() { 342 fn not_applicable_for_types_with_private_paths() {
343 check_assist_not_applicable( 343 check_assist_not_applicable(
344 qualify_path, 344 qualify_path,
345 r" 345 r#"
346 PrivateStruct$0 346PrivateStruct$0
347 347
348 pub mod PubMod { 348pub mod PubMod {
349 struct PrivateStruct; 349 struct PrivateStruct;
350 } 350}
351 ", 351"#,
352 ); 352 );
353 } 353 }
354 354
355 #[test] 355 #[test]
356 fn not_applicable_when_no_imports_found() { 356 fn not_applicable_when_no_imports_found() {
357 check_assist_not_applicable( 357 check_assist_not_applicable(qualify_path, r#"PubStruct$0"#);
358 qualify_path,
359 "
360 PubStruct$0",
361 );
362 } 358 }
363 359
364 #[test] 360 #[test]
365 fn not_applicable_in_import_statements() { 361 fn not_applicable_in_import_statements() {
366 check_assist_not_applicable( 362 check_assist_not_applicable(
367 qualify_path, 363 qualify_path,
368 r" 364 r#"
369 use PubStruct$0; 365use PubStruct$0;
370 366
371 pub mod PubMod { 367pub mod PubMod {
372 pub struct PubStruct; 368 pub struct PubStruct;
373 }", 369}
370"#,
374 ); 371 );
375 } 372 }
376 373
@@ -378,20 +375,20 @@ mod tests {
378 fn qualify_function() { 375 fn qualify_function() {
379 check_assist( 376 check_assist(
380 qualify_path, 377 qualify_path,
381 r" 378 r#"
382 test_function$0 379test_function$0
383 380
384 pub mod PubMod { 381pub mod PubMod {
385 pub fn test_function() {}; 382 pub fn test_function() {};
386 } 383}
387 ", 384"#,
388 r" 385 r#"
389 PubMod::test_function 386PubMod::test_function
390 387
391 pub mod PubMod { 388pub mod PubMod {
392 pub fn test_function() {}; 389 pub fn test_function() {};
393 } 390}
394 ", 391"#,
395 ); 392 );
396 } 393 }
397 394
@@ -399,7 +396,7 @@ mod tests {
399 fn qualify_macro() { 396 fn qualify_macro() {
400 check_assist( 397 check_assist(
401 qualify_path, 398 qualify_path,
402 r" 399 r#"
403//- /lib.rs crate:crate_with_macro 400//- /lib.rs crate:crate_with_macro
404#[macro_export] 401#[macro_export]
405macro_rules! foo { 402macro_rules! foo {
@@ -410,12 +407,12 @@ macro_rules! foo {
410fn main() { 407fn main() {
411 foo$0 408 foo$0
412} 409}
413", 410"#,
414 r" 411 r#"
415fn main() { 412fn main() {
416 crate_with_macro::foo 413 crate_with_macro::foo
417} 414}
418", 415"#,
419 ); 416 );
420 } 417 }
421 418
@@ -423,13 +420,13 @@ fn main() {
423 fn qualify_path_target() { 420 fn qualify_path_target() {
424 check_assist_target( 421 check_assist_target(
425 qualify_path, 422 qualify_path,
426 r" 423 r#"
427 struct AssistInfo { 424struct AssistInfo {
428 group_label: Option<$0GroupLabel>, 425 group_label: Option<$0GroupLabel>,
429 } 426}
430 427
431 mod m { pub struct GroupLabel; } 428mod m { pub struct GroupLabel; }
432 ", 429"#,
433 "GroupLabel", 430 "GroupLabel",
434 ) 431 )
435 } 432 }
@@ -438,20 +435,20 @@ fn main() {
438 fn not_applicable_when_path_start_is_imported() { 435 fn not_applicable_when_path_start_is_imported() {
439 check_assist_not_applicable( 436 check_assist_not_applicable(
440 qualify_path, 437 qualify_path,
441 r" 438 r#"
442 pub mod mod1 { 439pub mod mod1 {
443 pub mod mod2 { 440 pub mod mod2 {
444 pub mod mod3 { 441 pub mod mod3 {
445 pub struct TestStruct; 442 pub struct TestStruct;
446 } 443 }
447 } 444 }
448 } 445}
449 446
450 use mod1::mod2; 447use mod1::mod2;
451 fn main() { 448fn main() {
452 mod2::mod3::TestStruct$0 449 mod2::mod3::TestStruct$0
453 } 450}
454 ", 451"#,
455 ); 452 );
456 } 453 }
457 454
@@ -459,16 +456,16 @@ fn main() {
459 fn not_applicable_for_imported_function() { 456 fn not_applicable_for_imported_function() {
460 check_assist_not_applicable( 457 check_assist_not_applicable(
461 qualify_path, 458 qualify_path,
462 r" 459 r#"
463 pub mod test_mod { 460pub mod test_mod {
464 pub fn test_function() {} 461 pub fn test_function() {}
465 } 462}
466 463
467 use test_mod::test_function; 464use test_mod::test_function;
468 fn main() { 465fn main() {
469 test_function$0 466 test_function$0
470 } 467}
471 ", 468"#,
472 ); 469 );
473 } 470 }
474 471
@@ -476,30 +473,30 @@ fn main() {
476 fn associated_struct_function() { 473 fn associated_struct_function() {
477 check_assist( 474 check_assist(
478 qualify_path, 475 qualify_path,
479 r" 476 r#"
480 mod test_mod { 477mod test_mod {
481 pub struct TestStruct {} 478 pub struct TestStruct {}
482 impl TestStruct { 479 impl TestStruct {
483 pub fn test_function() {} 480 pub fn test_function() {}
484 } 481 }
485 } 482}
486 483
487 fn main() { 484fn main() {
488 TestStruct::test_function$0 485 TestStruct::test_function$0
489 } 486}
490 ", 487"#,
491 r" 488 r#"
492 mod test_mod { 489mod test_mod {
493 pub struct TestStruct {} 490 pub struct TestStruct {}
494 impl TestStruct { 491 impl TestStruct {
495 pub fn test_function() {} 492 pub fn test_function() {}
496 } 493 }
497 } 494}
498 495
499 fn main() { 496fn main() {
500 test_mod::TestStruct::test_function 497 test_mod::TestStruct::test_function
501 } 498}
502 ", 499"#,
503 ); 500 );
504 } 501 }
505 502
@@ -508,62 +505,50 @@ fn main() {
508 cov_mark::check!(qualify_path_qualifier_start); 505 cov_mark::check!(qualify_path_qualifier_start);
509 check_assist( 506 check_assist(
510 qualify_path, 507 qualify_path,
511 r" 508 r#"
512 mod test_mod { 509mod test_mod {
513 pub struct TestStruct {} 510 pub struct TestStruct {}
514 impl TestStruct { 511 impl TestStruct {
515 const TEST_CONST: u8 = 42; 512 const TEST_CONST: u8 = 42;
516 } 513 }
517 } 514}
518 515
519 fn main() { 516fn main() {
520 TestStruct::TEST_CONST$0 517 TestStruct::TEST_CONST$0
521 } 518}
522 ", 519"#,
523 r" 520 r#"
524 mod test_mod { 521mod test_mod {
525 pub struct TestStruct {} 522 pub struct TestStruct {}
526 impl TestStruct { 523 impl TestStruct {
527 const TEST_CONST: u8 = 42; 524 const TEST_CONST: u8 = 42;
528 } 525 }
529 } 526}
530 527
531 fn main() { 528fn main() {
532 test_mod::TestStruct::TEST_CONST 529 test_mod::TestStruct::TEST_CONST
533 } 530}
534 ", 531"#,
535 ); 532 );
536 } 533 }
537 534
538 #[test] 535 #[test]
539 #[ignore = "FIXME: non-trait assoc items completion is unsupported yet, see FIXME in the import_assets.rs for more details"]
540 fn associated_struct_const_unqualified() { 536 fn associated_struct_const_unqualified() {
541 check_assist( 537 // FIXME: non-trait assoc items completion is unsupported yet, see FIXME in the import_assets.rs for more details
538 check_assist_not_applicable(
542 qualify_path, 539 qualify_path,
543 r" 540 r#"
544 mod test_mod { 541mod test_mod {
545 pub struct TestStruct {} 542 pub struct TestStruct {}
546 impl TestStruct { 543 impl TestStruct {
547 const TEST_CONST: u8 = 42; 544 const TEST_CONST: u8 = 42;
548 } 545 }
549 } 546}
550
551 fn main() {
552 TEST_CONST$0
553 }
554 ",
555 r"
556 mod test_mod {
557 pub struct TestStruct {}
558 impl TestStruct {
559 const TEST_CONST: u8 = 42;
560 }
561 }
562 547
563 fn main() { 548fn main() {
564 test_mod::TestStruct::TEST_CONST 549 TEST_CONST$0
565 } 550}
566 ", 551"#,
567 ); 552 );
568 } 553 }
569 554
@@ -571,36 +556,36 @@ fn main() {
571 fn associated_trait_function() { 556 fn associated_trait_function() {
572 check_assist( 557 check_assist(
573 qualify_path, 558 qualify_path,
574 r" 559 r#"
575 mod test_mod { 560mod test_mod {
576 pub trait TestTrait { 561 pub trait TestTrait {
577 fn test_function(); 562 fn test_function();
578 } 563 }
579 pub struct TestStruct {} 564 pub struct TestStruct {}
580 impl TestTrait for TestStruct { 565 impl TestTrait for TestStruct {
581 fn test_function() {} 566 fn test_function() {}
582 } 567 }
583 } 568}
584 569
585 fn main() { 570fn main() {
586 test_mod::TestStruct::test_function$0 571 test_mod::TestStruct::test_function$0
587 } 572}
588 ", 573"#,
589 r" 574 r#"
590 mod test_mod { 575mod test_mod {
591 pub trait TestTrait { 576 pub trait TestTrait {
592 fn test_function(); 577 fn test_function();
593 } 578 }
594 pub struct TestStruct {} 579 pub struct TestStruct {}
595 impl TestTrait for TestStruct { 580 impl TestTrait for TestStruct {
596 fn test_function() {} 581 fn test_function() {}
597 } 582 }
598 } 583}
599 584
600 fn main() { 585fn main() {
601 <test_mod::TestStruct as test_mod::TestTrait>::test_function 586 <test_mod::TestStruct as test_mod::TestTrait>::test_function
602 } 587}
603 ", 588"#,
604 ); 589 );
605 } 590 }
606 591
@@ -608,31 +593,31 @@ fn main() {
608 fn not_applicable_for_imported_trait_for_function() { 593 fn not_applicable_for_imported_trait_for_function() {
609 check_assist_not_applicable( 594 check_assist_not_applicable(
610 qualify_path, 595 qualify_path,
611 r" 596 r#"
612 mod test_mod { 597mod test_mod {
613 pub trait TestTrait { 598 pub trait TestTrait {
614 fn test_function(); 599 fn test_function();
615 } 600 }
616 pub trait TestTrait2 { 601 pub trait TestTrait2 {
617 fn test_function(); 602 fn test_function();
618 } 603 }
619 pub enum TestEnum { 604 pub enum TestEnum {
620 One, 605 One,
621 Two, 606 Two,
622 } 607 }
623 impl TestTrait2 for TestEnum { 608 impl TestTrait2 for TestEnum {
624 fn test_function() {} 609 fn test_function() {}
625 } 610 }
626 impl TestTrait for TestEnum { 611 impl TestTrait for TestEnum {
627 fn test_function() {} 612 fn test_function() {}
628 } 613 }
629 } 614}
630 615
631 use test_mod::TestTrait2; 616use test_mod::TestTrait2;
632 fn main() { 617fn main() {
633 test_mod::TestEnum::test_function$0; 618 test_mod::TestEnum::test_function$0;
634 } 619}
635 ", 620"#,
636 ) 621 )
637 } 622 }
638 623
@@ -641,36 +626,36 @@ fn main() {
641 cov_mark::check!(qualify_path_trait_assoc_item); 626 cov_mark::check!(qualify_path_trait_assoc_item);
642 check_assist( 627 check_assist(
643 qualify_path, 628 qualify_path,
644 r" 629 r#"
645 mod test_mod { 630mod test_mod {
646 pub trait TestTrait { 631 pub trait TestTrait {
647 const TEST_CONST: u8; 632 const TEST_CONST: u8;
648 } 633 }
649 pub struct TestStruct {} 634 pub struct TestStruct {}
650 impl TestTrait for TestStruct { 635 impl TestTrait for TestStruct {
651 const TEST_CONST: u8 = 42; 636 const TEST_CONST: u8 = 42;
652 } 637 }
653 } 638}
654 639
655 fn main() { 640fn main() {
656 test_mod::TestStruct::TEST_CONST$0 641 test_mod::TestStruct::TEST_CONST$0
657 } 642}
658 ", 643"#,
659 r" 644 r#"
660 mod test_mod { 645mod test_mod {
661 pub trait TestTrait { 646 pub trait TestTrait {
662 const TEST_CONST: u8; 647 const TEST_CONST: u8;
663 } 648 }
664 pub struct TestStruct {} 649 pub struct TestStruct {}
665 impl TestTrait for TestStruct { 650 impl TestTrait for TestStruct {
666 const TEST_CONST: u8 = 42; 651 const TEST_CONST: u8 = 42;
667 } 652 }
668 } 653}
669 654
670 fn main() { 655fn main() {
671 <test_mod::TestStruct as test_mod::TestTrait>::TEST_CONST 656 <test_mod::TestStruct as test_mod::TestTrait>::TEST_CONST
672 } 657}
673 ", 658"#,
674 ); 659 );
675 } 660 }
676 661
@@ -678,31 +663,31 @@ fn main() {
678 fn not_applicable_for_imported_trait_for_const() { 663 fn not_applicable_for_imported_trait_for_const() {
679 check_assist_not_applicable( 664 check_assist_not_applicable(
680 qualify_path, 665 qualify_path,
681 r" 666 r#"
682 mod test_mod { 667mod test_mod {
683 pub trait TestTrait { 668 pub trait TestTrait {
684 const TEST_CONST: u8; 669 const TEST_CONST: u8;
685 } 670 }
686 pub trait TestTrait2 { 671 pub trait TestTrait2 {
687 const TEST_CONST: f64; 672 const TEST_CONST: f64;
688 } 673 }
689 pub enum TestEnum { 674 pub enum TestEnum {
690 One, 675 One,
691 Two, 676 Two,
692 } 677 }
693 impl TestTrait2 for TestEnum { 678 impl TestTrait2 for TestEnum {
694 const TEST_CONST: f64 = 42.0; 679 const TEST_CONST: f64 = 42.0;
695 } 680 }
696 impl TestTrait for TestEnum { 681 impl TestTrait for TestEnum {
697 const TEST_CONST: u8 = 42; 682 const TEST_CONST: u8 = 42;
698 } 683 }
699 } 684}
700 685
701 use test_mod::TestTrait2; 686use test_mod::TestTrait2;
702 fn main() { 687fn main() {
703 test_mod::TestEnum::TEST_CONST$0; 688 test_mod::TestEnum::TEST_CONST$0;
704 } 689}
705 ", 690"#,
706 ) 691 )
707 } 692 }
708 693
@@ -711,38 +696,38 @@ fn main() {
711 cov_mark::check!(qualify_path_trait_method); 696 cov_mark::check!(qualify_path_trait_method);
712 check_assist( 697 check_assist(
713 qualify_path, 698 qualify_path,
714 r" 699 r#"
715 mod test_mod { 700mod test_mod {
716 pub trait TestTrait { 701 pub trait TestTrait {
717 fn test_method(&self); 702 fn test_method(&self);
718 } 703 }
719 pub struct TestStruct {} 704 pub struct TestStruct {}
720 impl TestTrait for TestStruct { 705 impl TestTrait for TestStruct {
721 fn test_method(&self) {} 706 fn test_method(&self) {}
722 } 707 }
723 } 708}
724 709
725 fn main() { 710fn main() {
726 let test_struct = test_mod::TestStruct {}; 711 let test_struct = test_mod::TestStruct {};
727 test_struct.test_meth$0od() 712 test_struct.test_meth$0od()
728 } 713}
729 ", 714"#,
730 r" 715 r#"
731 mod test_mod { 716mod test_mod {
732 pub trait TestTrait { 717 pub trait TestTrait {
733 fn test_method(&self); 718 fn test_method(&self);
734 } 719 }
735 pub struct TestStruct {} 720 pub struct TestStruct {}
736 impl TestTrait for TestStruct { 721 impl TestTrait for TestStruct {
737 fn test_method(&self) {} 722 fn test_method(&self) {}
738 } 723 }
739 } 724}
740 725
741 fn main() { 726fn main() {
742 let test_struct = test_mod::TestStruct {}; 727 let test_struct = test_mod::TestStruct {};
743 test_mod::TestTrait::test_method(&test_struct) 728 test_mod::TestTrait::test_method(&test_struct)
744 } 729}
745 ", 730"#,
746 ); 731 );
747 } 732 }
748 733
@@ -750,38 +735,38 @@ fn main() {
750 fn trait_method_multi_params() { 735 fn trait_method_multi_params() {
751 check_assist( 736 check_assist(
752 qualify_path, 737 qualify_path,
753 r" 738 r#"
754 mod test_mod { 739mod test_mod {
755 pub trait TestTrait { 740 pub trait TestTrait {
756 fn test_method(&self, test: i32); 741 fn test_method(&self, test: i32);
757 } 742 }
758 pub struct TestStruct {} 743 pub struct TestStruct {}
759 impl TestTrait for TestStruct { 744 impl TestTrait for TestStruct {
760 fn test_method(&self, test: i32) {} 745 fn test_method(&self, test: i32) {}
761 } 746 }
762 } 747}
763 748
764 fn main() { 749fn main() {
765 let test_struct = test_mod::TestStruct {}; 750 let test_struct = test_mod::TestStruct {};
766 test_struct.test_meth$0od(42) 751 test_struct.test_meth$0od(42)
767 } 752}
768 ", 753"#,
769 r" 754 r#"
770 mod test_mod { 755mod test_mod {
771 pub trait TestTrait { 756 pub trait TestTrait {
772 fn test_method(&self, test: i32); 757 fn test_method(&self, test: i32);
773 } 758 }
774 pub struct TestStruct {} 759 pub struct TestStruct {}
775 impl TestTrait for TestStruct { 760 impl TestTrait for TestStruct {
776 fn test_method(&self, test: i32) {} 761 fn test_method(&self, test: i32) {}
777 } 762 }
778 } 763}
779 764
780 fn main() { 765fn main() {
781 let test_struct = test_mod::TestStruct {}; 766 let test_struct = test_mod::TestStruct {};
782 test_mod::TestTrait::test_method(&test_struct, 42) 767 test_mod::TestTrait::test_method(&test_struct, 42)
783 } 768}
784 ", 769"#,
785 ); 770 );
786 } 771 }
787 772
@@ -789,38 +774,38 @@ fn main() {
789 fn trait_method_consume() { 774 fn trait_method_consume() {
790 check_assist( 775 check_assist(
791 qualify_path, 776 qualify_path,
792 r" 777 r#"
793 mod test_mod { 778mod test_mod {
794 pub trait TestTrait { 779 pub trait TestTrait {
795 fn test_method(self); 780 fn test_method(self);
796 } 781 }
797 pub struct TestStruct {} 782 pub struct TestStruct {}
798 impl TestTrait for TestStruct { 783 impl TestTrait for TestStruct {
799 fn test_method(self) {} 784 fn test_method(self) {}
800 } 785 }
801 } 786}
802 787
803 fn main() { 788fn main() {
804 let test_struct = test_mod::TestStruct {}; 789 let test_struct = test_mod::TestStruct {};
805 test_struct.test_meth$0od() 790 test_struct.test_meth$0od()
806 } 791}
807 ", 792"#,
808 r" 793 r#"
809 mod test_mod { 794mod test_mod {
810 pub trait TestTrait { 795 pub trait TestTrait {
811 fn test_method(self); 796 fn test_method(self);
812 } 797 }
813 pub struct TestStruct {} 798 pub struct TestStruct {}
814 impl TestTrait for TestStruct { 799 impl TestTrait for TestStruct {
815 fn test_method(self) {} 800 fn test_method(self) {}
816 } 801 }
817 } 802}
818 803
819 fn main() { 804fn main() {
820 let test_struct = test_mod::TestStruct {}; 805 let test_struct = test_mod::TestStruct {};
821 test_mod::TestTrait::test_method(test_struct) 806 test_mod::TestTrait::test_method(test_struct)
822 } 807}
823 ", 808"#,
824 ); 809 );
825 } 810 }
826 811
@@ -828,29 +813,29 @@ fn main() {
828 fn trait_method_cross_crate() { 813 fn trait_method_cross_crate() {
829 check_assist( 814 check_assist(
830 qualify_path, 815 qualify_path,
831 r" 816 r#"
832 //- /main.rs crate:main deps:dep 817//- /main.rs crate:main deps:dep
833 fn main() { 818fn main() {
834 let test_struct = dep::test_mod::TestStruct {}; 819 let test_struct = dep::test_mod::TestStruct {};
835 test_struct.test_meth$0od() 820 test_struct.test_meth$0od()
836 } 821}
837 //- /dep.rs crate:dep 822//- /dep.rs crate:dep
838 pub mod test_mod { 823pub mod test_mod {
839 pub trait TestTrait { 824 pub trait TestTrait {
840 fn test_method(&self); 825 fn test_method(&self);
841 } 826 }
842 pub struct TestStruct {} 827 pub struct TestStruct {}
843 impl TestTrait for TestStruct { 828 impl TestTrait for TestStruct {
844 fn test_method(&self) {} 829 fn test_method(&self) {}
845 } 830 }
846 } 831}
847 ", 832"#,
848 r" 833 r#"
849 fn main() { 834fn main() {
850 let test_struct = dep::test_mod::TestStruct {}; 835 let test_struct = dep::test_mod::TestStruct {};
851 dep::test_mod::TestTrait::test_method(&test_struct) 836 dep::test_mod::TestTrait::test_method(&test_struct)
852 } 837}
853 ", 838"#,
854 ); 839 );
855 } 840 }
856 841
@@ -858,27 +843,27 @@ fn main() {
858 fn assoc_fn_cross_crate() { 843 fn assoc_fn_cross_crate() {
859 check_assist( 844 check_assist(
860 qualify_path, 845 qualify_path,
861 r" 846 r#"
862 //- /main.rs crate:main deps:dep 847//- /main.rs crate:main deps:dep
863 fn main() { 848fn main() {
864 dep::test_mod::TestStruct::test_func$0tion 849 dep::test_mod::TestStruct::test_func$0tion
865 } 850}
866 //- /dep.rs crate:dep 851//- /dep.rs crate:dep
867 pub mod test_mod { 852pub mod test_mod {
868 pub trait TestTrait { 853 pub trait TestTrait {
869 fn test_function(); 854 fn test_function();
870 } 855 }
871 pub struct TestStruct {} 856 pub struct TestStruct {}
872 impl TestTrait for TestStruct { 857 impl TestTrait for TestStruct {
873 fn test_function() {} 858 fn test_function() {}
874 } 859 }
875 } 860}
876 ", 861"#,
877 r" 862 r#"
878 fn main() { 863fn main() {
879 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::test_function 864 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::test_function
880 } 865}
881 ", 866"#,
882 ); 867 );
883 } 868 }
884 869
@@ -886,27 +871,27 @@ fn main() {
886 fn assoc_const_cross_crate() { 871 fn assoc_const_cross_crate() {
887 check_assist( 872 check_assist(
888 qualify_path, 873 qualify_path,
889 r" 874 r#"
890 //- /main.rs crate:main deps:dep 875//- /main.rs crate:main deps:dep
891 fn main() { 876fn main() {
892 dep::test_mod::TestStruct::CONST$0 877 dep::test_mod::TestStruct::CONST$0
893 } 878}
894 //- /dep.rs crate:dep 879//- /dep.rs crate:dep
895 pub mod test_mod { 880pub mod test_mod {
896 pub trait TestTrait { 881 pub trait TestTrait {
897 const CONST: bool; 882 const CONST: bool;
898 } 883 }
899 pub struct TestStruct {} 884 pub struct TestStruct {}
900 impl TestTrait for TestStruct { 885 impl TestTrait for TestStruct {
901 const CONST: bool = true; 886 const CONST: bool = true;
902 } 887 }
903 } 888}
904 ", 889"#,
905 r" 890 r#"
906 fn main() { 891fn main() {
907 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::CONST 892 <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::CONST
908 } 893}
909 ", 894"#,
910 ); 895 );
911 } 896 }
912 897
@@ -914,23 +899,23 @@ fn main() {
914 fn assoc_fn_as_method_cross_crate() { 899 fn assoc_fn_as_method_cross_crate() {
915 check_assist_not_applicable( 900 check_assist_not_applicable(
916 qualify_path, 901 qualify_path,
917 r" 902 r#"
918 //- /main.rs crate:main deps:dep 903//- /main.rs crate:main deps:dep
919 fn main() { 904fn main() {
920 let test_struct = dep::test_mod::TestStruct {}; 905 let test_struct = dep::test_mod::TestStruct {};
921 test_struct.test_func$0tion() 906 test_struct.test_func$0tion()
922 } 907}
923 //- /dep.rs crate:dep 908//- /dep.rs crate:dep
924 pub mod test_mod { 909pub mod test_mod {
925 pub trait TestTrait { 910 pub trait TestTrait {
926 fn test_function(); 911 fn test_function();
927 } 912 }
928 pub struct TestStruct {} 913 pub struct TestStruct {}
929 impl TestTrait for TestStruct { 914 impl TestTrait for TestStruct {
930 fn test_function() {} 915 fn test_function() {}
931 } 916 }
932 } 917}
933 ", 918"#,
934 ); 919 );
935 } 920 }
936 921
@@ -938,23 +923,23 @@ fn main() {
938 fn private_trait_cross_crate() { 923 fn private_trait_cross_crate() {
939 check_assist_not_applicable( 924 check_assist_not_applicable(
940 qualify_path, 925 qualify_path,
941 r" 926 r#"
942 //- /main.rs crate:main deps:dep 927//- /main.rs crate:main deps:dep
943 fn main() { 928fn main() {
944 let test_struct = dep::test_mod::TestStruct {}; 929 let test_struct = dep::test_mod::TestStruct {};
945 test_struct.test_meth$0od() 930 test_struct.test_meth$0od()
946 } 931}
947 //- /dep.rs crate:dep 932//- /dep.rs crate:dep
948 pub mod test_mod { 933pub mod test_mod {
949 trait TestTrait { 934 trait TestTrait {
950 fn test_method(&self); 935 fn test_method(&self);
951 } 936 }
952 pub struct TestStruct {} 937 pub struct TestStruct {}
953 impl TestTrait for TestStruct { 938 impl TestTrait for TestStruct {
954 fn test_method(&self) {} 939 fn test_method(&self) {}
955 } 940 }
956 } 941}
957 ", 942"#,
958 ); 943 );
959 } 944 }
960 945
@@ -962,32 +947,32 @@ fn main() {
962 fn not_applicable_for_imported_trait_for_method() { 947 fn not_applicable_for_imported_trait_for_method() {
963 check_assist_not_applicable( 948 check_assist_not_applicable(
964 qualify_path, 949 qualify_path,
965 r" 950 r#"
966 mod test_mod { 951mod test_mod {
967 pub trait TestTrait { 952 pub trait TestTrait {
968 fn test_method(&self); 953 fn test_method(&self);
969 } 954 }
970 pub trait TestTrait2 { 955 pub trait TestTrait2 {
971 fn test_method(&self); 956 fn test_method(&self);
972 } 957 }
973 pub enum TestEnum { 958 pub enum TestEnum {
974 One, 959 One,
975 Two, 960 Two,
976 } 961 }
977 impl TestTrait2 for TestEnum { 962 impl TestTrait2 for TestEnum {
978 fn test_method(&self) {} 963 fn test_method(&self) {}
979 } 964 }
980 impl TestTrait for TestEnum { 965 impl TestTrait for TestEnum {
981 fn test_method(&self) {} 966 fn test_method(&self) {}
982 } 967 }
983 } 968}
984 969
985 use test_mod::TestTrait2; 970use test_mod::TestTrait2;
986 fn main() { 971fn main() {
987 let one = test_mod::TestEnum::One; 972 let one = test_mod::TestEnum::One;
988 one.test$0_method(); 973 one.test$0_method();
989 } 974}
990 ", 975"#,
991 ) 976 )
992 } 977 }
993 978
@@ -1114,7 +1099,7 @@ fn main() {}
1114 fn keep_generic_annotations_leading_colon() { 1099 fn keep_generic_annotations_leading_colon() {
1115 check_assist( 1100 check_assist(
1116 qualify_path, 1101 qualify_path,
1117 r" 1102 r#"
1118//- /lib.rs crate:dep 1103//- /lib.rs crate:dep
1119pub mod generic { pub struct Thing<'a, T>(&'a T); } 1104pub mod generic { pub struct Thing<'a, T>(&'a T); }
1120 1105
@@ -1122,7 +1107,7 @@ pub mod generic { pub struct Thing<'a, T>(&'a T); }
1122fn foo() -> Thin$0g::<'static, ()> {} 1107fn foo() -> Thin$0g::<'static, ()> {}
1123 1108
1124fn main() {} 1109fn main() {}
1125", 1110"#,
1126 r" 1111 r"
1127fn foo() -> dep::generic::Thing::<'static, ()> {} 1112fn foo() -> dep::generic::Thing::<'static, ()> {}
1128 1113
@@ -1135,30 +1120,30 @@ fn main() {}
1135 fn associated_struct_const_generic() { 1120 fn associated_struct_const_generic() {
1136 check_assist( 1121 check_assist(
1137 qualify_path, 1122 qualify_path,
1138 r" 1123 r#"
1139 mod test_mod { 1124mod test_mod {
1140 pub struct TestStruct<T> {} 1125 pub struct TestStruct<T> {}
1141 impl<T> TestStruct<T> { 1126 impl<T> TestStruct<T> {
1142 const TEST_CONST: u8 = 42; 1127 const TEST_CONST: u8 = 42;
1143 } 1128 }
1144 } 1129}
1145 1130
1146 fn main() { 1131fn main() {
1147 TestStruct::<()>::TEST_CONST$0 1132 TestStruct::<()>::TEST_CONST$0
1148 } 1133}
1149 ", 1134"#,
1150 r" 1135 r#"
1151 mod test_mod { 1136mod test_mod {
1152 pub struct TestStruct<T> {} 1137 pub struct TestStruct<T> {}
1153 impl<T> TestStruct<T> { 1138 impl<T> TestStruct<T> {
1154 const TEST_CONST: u8 = 42; 1139 const TEST_CONST: u8 = 42;
1155 } 1140 }
1156 } 1141}
1157 1142
1158 fn main() { 1143fn main() {
1159 test_mod::TestStruct::<()>::TEST_CONST 1144 test_mod::TestStruct::<()>::TEST_CONST
1160 } 1145}
1161 ", 1146"#,
1162 ); 1147 );
1163 } 1148 }
1164 1149
@@ -1166,36 +1151,36 @@ fn main() {}
1166 fn associated_trait_const_generic() { 1151 fn associated_trait_const_generic() {
1167 check_assist( 1152 check_assist(
1168 qualify_path, 1153 qualify_path,
1169 r" 1154 r#"
1170 mod test_mod { 1155mod test_mod {
1171 pub trait TestTrait { 1156 pub trait TestTrait {
1172 const TEST_CONST: u8; 1157 const TEST_CONST: u8;
1173 } 1158 }
1174 pub struct TestStruct<T> {} 1159 pub struct TestStruct<T> {}
1175 impl<T> TestTrait for TestStruct<T> { 1160 impl<T> TestTrait for TestStruct<T> {
1176 const TEST_CONST: u8 = 42; 1161 const TEST_CONST: u8 = 42;
1177 } 1162 }
1178 } 1163}
1179 1164
1180 fn main() { 1165fn main() {
1181 test_mod::TestStruct::<()>::TEST_CONST$0 1166 test_mod::TestStruct::<()>::TEST_CONST$0
1182 } 1167}
1183 ", 1168"#,
1184 r" 1169 r#"
1185 mod test_mod { 1170mod test_mod {
1186 pub trait TestTrait { 1171 pub trait TestTrait {
1187 const TEST_CONST: u8; 1172 const TEST_CONST: u8;
1188 } 1173 }
1189 pub struct TestStruct<T> {} 1174 pub struct TestStruct<T> {}
1190 impl<T> TestTrait for TestStruct<T> { 1175 impl<T> TestTrait for TestStruct<T> {
1191 const TEST_CONST: u8 = 42; 1176 const TEST_CONST: u8 = 42;
1192 } 1177 }
1193 } 1178}
1194 1179
1195 fn main() { 1180fn main() {
1196 <test_mod::TestStruct::<()> as test_mod::TestTrait>::TEST_CONST 1181 <test_mod::TestStruct::<()> as test_mod::TestTrait>::TEST_CONST
1197 } 1182}
1198 ", 1183"#,
1199 ); 1184 );
1200 } 1185 }
1201 1186
@@ -1203,38 +1188,38 @@ fn main() {}
1203 fn trait_method_generic() { 1188 fn trait_method_generic() {
1204 check_assist( 1189 check_assist(
1205 qualify_path, 1190 qualify_path,
1206 r" 1191 r#"
1207 mod test_mod { 1192mod test_mod {
1208 pub trait TestTrait { 1193 pub trait TestTrait {
1209 fn test_method<T>(&self); 1194 fn test_method<T>(&self);
1210 } 1195 }
1211 pub struct TestStruct {} 1196 pub struct TestStruct {}
1212 impl TestTrait for TestStruct { 1197 impl TestTrait for TestStruct {
1213 fn test_method<T>(&self) {} 1198 fn test_method<T>(&self) {}
1214 } 1199 }
1215 } 1200}
1216 1201
1217 fn main() { 1202fn main() {
1218 let test_struct = test_mod::TestStruct {}; 1203 let test_struct = test_mod::TestStruct {};
1219 test_struct.test_meth$0od::<()>() 1204 test_struct.test_meth$0od::<()>()
1220 } 1205}
1221 ", 1206"#,
1222 r" 1207 r#"
1223 mod test_mod { 1208mod test_mod {
1224 pub trait TestTrait { 1209 pub trait TestTrait {
1225 fn test_method<T>(&self); 1210 fn test_method<T>(&self);
1226 } 1211 }
1227 pub struct TestStruct {} 1212 pub struct TestStruct {}
1228 impl TestTrait for TestStruct { 1213 impl TestTrait for TestStruct {
1229 fn test_method<T>(&self) {} 1214 fn test_method<T>(&self) {}
1230 } 1215 }
1231 } 1216}
1232 1217
1233 fn main() { 1218fn main() {
1234 let test_struct = test_mod::TestStruct {}; 1219 let test_struct = test_mod::TestStruct {};
1235 test_mod::TestTrait::test_method::<()>(&test_struct) 1220 test_mod::TestTrait::test_method::<()>(&test_struct)
1236 } 1221}
1237 ", 1222"#,
1238 ); 1223 );
1239 } 1224 }
1240} 1225}
diff --git a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs
index 540a905cc..a2af2035f 100644
--- a/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs
+++ b/crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs
@@ -105,12 +105,13 @@ fn foo<B: Bar
105 } 105 }
106 106
107 #[test] 107 #[test]
108 #[ignore = "This case is very rare but there is no simple solutions to fix it."]
109 fn replace_impl_trait_with_exist_generic_letter() { 108 fn replace_impl_trait_with_exist_generic_letter() {
109 // FIXME: This is wrong, we should pick a different name if the one we
110 // want is already bound.
110 check_assist( 111 check_assist(
111 replace_impl_trait_with_generic, 112 replace_impl_trait_with_generic,
112 r#"fn foo<B>(bar: $0impl Bar) {}"#, 113 r#"fn foo<B>(bar: $0impl Bar) {}"#,
113 r#"fn foo<B, C: Bar>(bar: C) {}"#, 114 r#"fn foo<B, B: Bar>(bar: B) {}"#,
114 ); 115 );
115 } 116 }
116 117
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 331a6df2b..fa378a622 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -17,156 +17,31 @@ mod tests;
17pub mod utils; 17pub mod utils;
18pub mod path_transform; 18pub mod path_transform;
19 19
20use std::str::FromStr;
21
22use hir::Semantics; 20use hir::Semantics;
23use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase}; 21use ide_db::{base_db::FileRange, RootDatabase};
24use syntax::TextRange; 22use syntax::TextRange;
25 23
26pub(crate) use crate::assist_context::{AssistContext, Assists}; 24pub(crate) use crate::assist_context::{AssistContext, Assists};
27 25
28pub use assist_config::AssistConfig; 26pub use assist_config::AssistConfig;
29 27pub use ide_db::assists::{
30#[derive(Debug, Clone, Copy, PartialEq, Eq)] 28 Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel, SingleResolve,
31pub enum AssistKind { 29};
32 // FIXME: does the None variant make sense? Probably not. 30
33 None, 31/// Return all the assists applicable at the given position.
34 32pub fn assists(
35 QuickFix, 33 db: &RootDatabase,
36 Generate, 34 config: &AssistConfig,
37 Refactor, 35 resolve: AssistResolveStrategy,
38 RefactorExtract, 36 range: FileRange,
39 RefactorInline, 37) -> Vec<Assist> {
40 RefactorRewrite, 38 let sema = Semantics::new(db);
41} 39 let ctx = AssistContext::new(sema, config, range);
42 40 let mut acc = Assists::new(&ctx, resolve);
43impl AssistKind { 41 handlers::all().iter().for_each(|handler| {
44 pub fn contains(self, other: AssistKind) -> bool { 42 handler(&mut acc, &ctx);
45 if self == other { 43 });
46 return true; 44 acc.finish()
47 }
48
49 match self {
50 AssistKind::None | AssistKind::Generate => true,
51 AssistKind::Refactor => match other {
52 AssistKind::RefactorExtract
53 | AssistKind::RefactorInline
54 | AssistKind::RefactorRewrite => true,
55 _ => false,
56 },
57 _ => false,
58 }
59 }
60
61 pub fn name(&self) -> &str {
62 match self {
63 AssistKind::None => "None",
64 AssistKind::QuickFix => "QuickFix",
65 AssistKind::Generate => "Generate",
66 AssistKind::Refactor => "Refactor",
67 AssistKind::RefactorExtract => "RefactorExtract",
68 AssistKind::RefactorInline => "RefactorInline",
69 AssistKind::RefactorRewrite => "RefactorRewrite",
70 }
71 }
72}
73
74impl FromStr for AssistKind {
75 type Err = String;
76
77 fn from_str(s: &str) -> Result<Self, Self::Err> {
78 match s {
79 "None" => Ok(AssistKind::None),
80 "QuickFix" => Ok(AssistKind::QuickFix),
81 "Generate" => Ok(AssistKind::Generate),
82 "Refactor" => Ok(AssistKind::Refactor),
83 "RefactorExtract" => Ok(AssistKind::RefactorExtract),
84 "RefactorInline" => Ok(AssistKind::RefactorInline),
85 "RefactorRewrite" => Ok(AssistKind::RefactorRewrite),
86 unknown => Err(format!("Unknown AssistKind: '{}'", unknown)),
87 }
88 }
89}
90
91/// Unique identifier of the assist, should not be shown to the user
92/// directly.
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub struct AssistId(pub &'static str, pub AssistKind);
95
96/// A way to control how many asssist to resolve during the assist resolution.
97/// When an assist is resolved, its edits are calculated that might be costly to always do by default.
98#[derive(Debug)]
99pub enum AssistResolveStrategy {
100 /// No assists should be resolved.
101 None,
102 /// All assists should be resolved.
103 All,
104 /// Only a certain assist should be resolved.
105 Single(SingleResolve),
106}
107
108/// Hold the [`AssistId`] data of a certain assist to resolve.
109/// The original id object cannot be used due to a `'static` lifetime
110/// and the requirement to construct this struct dynamically during the resolve handling.
111#[derive(Debug)]
112pub struct SingleResolve {
113 /// The id of the assist.
114 pub assist_id: String,
115 // The kind of the assist.
116 pub assist_kind: AssistKind,
117}
118
119impl AssistResolveStrategy {
120 pub fn should_resolve(&self, id: &AssistId) -> bool {
121 match self {
122 AssistResolveStrategy::None => false,
123 AssistResolveStrategy::All => true,
124 AssistResolveStrategy::Single(single_resolve) => {
125 single_resolve.assist_id == id.0 && single_resolve.assist_kind == id.1
126 }
127 }
128 }
129}
130
131#[derive(Clone, Debug)]
132pub struct GroupLabel(pub String);
133
134#[derive(Debug, Clone)]
135pub struct Assist {
136 pub id: AssistId,
137 /// Short description of the assist, as shown in the UI.
138 pub label: Label,
139 pub group: Option<GroupLabel>,
140 /// Target ranges are used to sort assists: the smaller the target range,
141 /// the more specific assist is, and so it should be sorted first.
142 pub target: TextRange,
143 /// Computing source change sometimes is much more costly then computing the
144 /// other fields. Additionally, the actual change is not required to show
145 /// the lightbulb UI, it only is needed when the user tries to apply an
146 /// assist. So, we compute it lazily: the API allow requesting assists with
147 /// or without source change. We could (and in fact, used to) distinguish
148 /// between resolved and unresolved assists at the type level, but this is
149 /// cumbersome, especially if you want to embed an assist into another data
150 /// structure, such as a diagnostic.
151 pub source_change: Option<SourceChange>,
152}
153
154impl Assist {
155 /// Return all the assists applicable at the given position.
156 pub fn get(
157 db: &RootDatabase,
158 config: &AssistConfig,
159 resolve: AssistResolveStrategy,
160 range: FileRange,
161 ) -> Vec<Assist> {
162 let sema = Semantics::new(db);
163 let ctx = AssistContext::new(sema, config, range);
164 let mut acc = Assists::new(&ctx, resolve);
165 handlers::all().iter().for_each(|handler| {
166 handler(&mut acc, &ctx);
167 });
168 acc.finish()
169 }
170} 45}
171 46
172mod handlers { 47mod handlers {
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index bdf9cb71c..60cecd94c 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -16,8 +16,8 @@ use syntax::TextRange;
16use test_utils::{assert_eq_text, extract_offset}; 16use test_utils::{assert_eq_text, extract_offset};
17 17
18use crate::{ 18use crate::{
19 handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, AssistResolveStrategy, 19 assists, handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind,
20 Assists, SingleResolve, 20 AssistResolveStrategy, Assists, SingleResolve,
21}; 21};
22 22
23pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { 23pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
@@ -78,14 +78,14 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
78 let before = db.file_text(file_id).to_string(); 78 let before = db.file_text(file_id).to_string();
79 let frange = FileRange { file_id, range: selection.into() }; 79 let frange = FileRange { file_id, range: selection.into() };
80 80
81 let assist = Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::All, frange) 81 let assist = assists(&db, &TEST_CONFIG, AssistResolveStrategy::All, frange)
82 .into_iter() 82 .into_iter()
83 .find(|assist| assist.id.0 == assist_id) 83 .find(|assist| assist.id.0 == assist_id)
84 .unwrap_or_else(|| { 84 .unwrap_or_else(|| {
85 panic!( 85 panic!(
86 "\n\nAssist is not applicable: {}\nAvailable assists: {}", 86 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
87 assist_id, 87 assist_id,
88 Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange) 88 assists(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange)
89 .into_iter() 89 .into_iter()
90 .map(|assist| assist.id.0) 90 .map(|assist| assist.id.0)
91 .collect::<Vec<_>>() 91 .collect::<Vec<_>>()
@@ -210,7 +210,7 @@ fn assist_order_field_struct() {
210 let (before_cursor_pos, before) = extract_offset(before); 210 let (before_cursor_pos, before) = extract_offset(before);
211 let (db, file_id) = with_single_file(&before); 211 let (db, file_id) = with_single_file(&before);
212 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; 212 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
213 let assists = Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange); 213 let assists = assists(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange);
214 let mut assists = assists.iter(); 214 let mut assists = assists.iter();
215 215
216 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)"); 216 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)");
@@ -235,7 +235,7 @@ pub fn test_some_range(a: int) -> bool {
235"#, 235"#,
236 ); 236 );
237 237
238 let assists = Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange); 238 let assists = assists(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange);
239 let expected = labels(&assists); 239 let expected = labels(&assists);
240 240
241 expect![[r#" 241 expect![[r#"
@@ -264,7 +264,7 @@ pub fn test_some_range(a: int) -> bool {
264 let mut cfg = TEST_CONFIG; 264 let mut cfg = TEST_CONFIG;
265 cfg.allowed = Some(vec![AssistKind::Refactor]); 265 cfg.allowed = Some(vec![AssistKind::Refactor]);
266 266
267 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::None, frange); 267 let assists = assists(&db, &cfg, AssistResolveStrategy::None, frange);
268 let expected = labels(&assists); 268 let expected = labels(&assists);
269 269
270 expect![[r#" 270 expect![[r#"
@@ -279,7 +279,7 @@ pub fn test_some_range(a: int) -> bool {
279 { 279 {
280 let mut cfg = TEST_CONFIG; 280 let mut cfg = TEST_CONFIG;
281 cfg.allowed = Some(vec![AssistKind::RefactorExtract]); 281 cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
282 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::None, frange); 282 let assists = assists(&db, &cfg, AssistResolveStrategy::None, frange);
283 let expected = labels(&assists); 283 let expected = labels(&assists);
284 284
285 expect![[r#" 285 expect![[r#"
@@ -292,7 +292,7 @@ pub fn test_some_range(a: int) -> bool {
292 { 292 {
293 let mut cfg = TEST_CONFIG; 293 let mut cfg = TEST_CONFIG;
294 cfg.allowed = Some(vec![AssistKind::QuickFix]); 294 cfg.allowed = Some(vec![AssistKind::QuickFix]);
295 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::None, frange); 295 let assists = assists(&db, &cfg, AssistResolveStrategy::None, frange);
296 let expected = labels(&assists); 296 let expected = labels(&assists);
297 297
298 expect![[r#""#]].assert_eq(&expected); 298 expect![[r#""#]].assert_eq(&expected);
@@ -317,7 +317,7 @@ pub fn test_some_range(a: int) -> bool {
317 cfg.allowed = Some(vec![AssistKind::RefactorExtract]); 317 cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
318 318
319 { 319 {
320 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::None, frange); 320 let assists = assists(&db, &cfg, AssistResolveStrategy::None, frange);
321 assert_eq!(2, assists.len()); 321 assert_eq!(2, assists.len());
322 let mut assists = assists.into_iter(); 322 let mut assists = assists.into_iter();
323 323
@@ -353,7 +353,7 @@ pub fn test_some_range(a: int) -> bool {
353 } 353 }
354 354
355 { 355 {
356 let assists = Assist::get( 356 let assists = assists(
357 &db, 357 &db,
358 &cfg, 358 &cfg,
359 AssistResolveStrategy::Single(SingleResolve { 359 AssistResolveStrategy::Single(SingleResolve {
@@ -397,7 +397,7 @@ pub fn test_some_range(a: int) -> bool {
397 } 397 }
398 398
399 { 399 {
400 let assists = Assist::get( 400 let assists = assists(
401 &db, 401 &db,
402 &cfg, 402 &cfg,
403 AssistResolveStrategy::Single(SingleResolve { 403 AssistResolveStrategy::Single(SingleResolve {
@@ -462,7 +462,7 @@ pub fn test_some_range(a: int) -> bool {
462 } 462 }
463 463
464 { 464 {
465 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::All, frange); 465 let assists = assists(&db, &cfg, AssistResolveStrategy::All, frange);
466 assert_eq!(2, assists.len()); 466 assert_eq!(2, assists.len());
467 let mut assists = assists.into_iter(); 467 let mut assists = assists.into_iter();
468 468