|
1 | 1 | use std::collections::HashSet;
|
2 | 2 |
|
3 | 3 | use hir::{self, HasCrate, HasSource, HasVisibility};
|
| 4 | +use ide_db::path_transform::PathTransform; |
4 | 5 | use syntax::{
|
5 | 6 | ast::{
|
6 | 7 | self, edit_in_place::Indent, make, AstNode, HasGenericParams, HasName, HasVisibility as _,
|
@@ -106,7 +107,10 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
106 | 107 | |edit| {
|
107 | 108 | // Create the function
|
108 | 109 | let method_source = match method.source(ctx.db()) {
|
109 |
| - Some(source) => source.value, |
| 110 | + Some(source) => { |
| 111 | + ctx.sema.parse_or_expand(source.file_id); |
| 112 | + source.value |
| 113 | + } |
110 | 114 | None => return,
|
111 | 115 | };
|
112 | 116 | let vis = method_source.visibility();
|
@@ -183,6 +187,12 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
183 | 187 | let assoc_items = impl_def.get_or_create_assoc_item_list();
|
184 | 188 | assoc_items.add_item(f.clone().into());
|
185 | 189 |
|
| 190 | + PathTransform::generic_transformation( |
| 191 | + &ctx.sema.scope(strukt.syntax()).unwrap(), |
| 192 | + &ctx.sema.scope(method_source.syntax()).unwrap(), |
| 193 | + ) |
| 194 | + .apply(f.syntax()); |
| 195 | + |
186 | 196 | if let Some(cap) = ctx.config.snippet_cap {
|
187 | 197 | edit.add_tabstop_before(cap, f)
|
188 | 198 | }
|
@@ -454,6 +464,162 @@ impl Person {
|
454 | 464 | );
|
455 | 465 | }
|
456 | 466 |
|
| 467 | + #[test] |
| 468 | + fn test_fixes_basic_self_references() { |
| 469 | + check_assist( |
| 470 | + generate_delegate_methods, |
| 471 | + r#" |
| 472 | +struct Foo { |
| 473 | + field: $0Bar, |
| 474 | +} |
| 475 | +
|
| 476 | +struct Bar; |
| 477 | +
|
| 478 | +impl Bar { |
| 479 | + fn bar(&self, other: Self) -> Self { |
| 480 | + other |
| 481 | + } |
| 482 | +} |
| 483 | +"#, |
| 484 | + r#" |
| 485 | +struct Foo { |
| 486 | + field: Bar, |
| 487 | +} |
| 488 | +
|
| 489 | +impl Foo { |
| 490 | + $0fn bar(&self, other: Bar) -> Bar { |
| 491 | + self.field.bar(other) |
| 492 | + } |
| 493 | +} |
| 494 | +
|
| 495 | +struct Bar; |
| 496 | +
|
| 497 | +impl Bar { |
| 498 | + fn bar(&self, other: Self) -> Self { |
| 499 | + other |
| 500 | + } |
| 501 | +} |
| 502 | +"#, |
| 503 | + ); |
| 504 | + } |
| 505 | + |
| 506 | + #[test] |
| 507 | + fn test_fixes_nested_self_references() { |
| 508 | + check_assist( |
| 509 | + generate_delegate_methods, |
| 510 | + r#" |
| 511 | +struct Foo { |
| 512 | + field: $0Bar, |
| 513 | +} |
| 514 | +
|
| 515 | +struct Bar; |
| 516 | +
|
| 517 | +impl Bar { |
| 518 | + fn bar(&mut self, a: (Self, [Self; 4]), b: Vec<Self>) {} |
| 519 | +} |
| 520 | +"#, |
| 521 | + r#" |
| 522 | +struct Foo { |
| 523 | + field: Bar, |
| 524 | +} |
| 525 | +
|
| 526 | +impl Foo { |
| 527 | + $0fn bar(&mut self, a: (Bar, [Bar; 4]), b: Vec<Bar>) { |
| 528 | + self.field.bar(a, b) |
| 529 | + } |
| 530 | +} |
| 531 | +
|
| 532 | +struct Bar; |
| 533 | +
|
| 534 | +impl Bar { |
| 535 | + fn bar(&mut self, a: (Self, [Self; 4]), b: Vec<Self>) {} |
| 536 | +} |
| 537 | +"#, |
| 538 | + ); |
| 539 | + } |
| 540 | + |
| 541 | + #[test] |
| 542 | + fn test_fixes_self_references_with_lifetimes_and_generics() { |
| 543 | + check_assist( |
| 544 | + generate_delegate_methods, |
| 545 | + r#" |
| 546 | +struct Foo<'a, T> { |
| 547 | + $0field: Bar<'a, T>, |
| 548 | +} |
| 549 | +
|
| 550 | +struct Bar<'a, T>(&'a T); |
| 551 | +
|
| 552 | +impl<'a, T> Bar<'a, T> { |
| 553 | + fn bar(self, mut b: Vec<&'a Self>) -> &'a Self { |
| 554 | + b.pop().unwrap() |
| 555 | + } |
| 556 | +} |
| 557 | +"#, |
| 558 | + r#" |
| 559 | +struct Foo<'a, T> { |
| 560 | + field: Bar<'a, T>, |
| 561 | +} |
| 562 | +
|
| 563 | +impl<'a, T> Foo<'a, T> { |
| 564 | + $0fn bar(self, mut b: Vec<&'a Bar<'_, T>>) -> &'a Bar<'_, T> { |
| 565 | + self.field.bar(b) |
| 566 | + } |
| 567 | +} |
| 568 | +
|
| 569 | +struct Bar<'a, T>(&'a T); |
| 570 | +
|
| 571 | +impl<'a, T> Bar<'a, T> { |
| 572 | + fn bar(self, mut b: Vec<&'a Self>) -> &'a Self { |
| 573 | + b.pop().unwrap() |
| 574 | + } |
| 575 | +} |
| 576 | +"#, |
| 577 | + ); |
| 578 | + } |
| 579 | + |
| 580 | + #[test] |
| 581 | + fn test_fixes_self_references_across_macros() { |
| 582 | + check_assist( |
| 583 | + generate_delegate_methods, |
| 584 | + r#" |
| 585 | +//- /bar.rs |
| 586 | +macro_rules! test_method { |
| 587 | + () => { |
| 588 | + pub fn test(self, b: Bar) -> Self { |
| 589 | + self |
| 590 | + } |
| 591 | + }; |
| 592 | +} |
| 593 | +
|
| 594 | +pub struct Bar; |
| 595 | +
|
| 596 | +impl Bar { |
| 597 | + test_method!(); |
| 598 | +} |
| 599 | +
|
| 600 | +//- /main.rs |
| 601 | +mod bar; |
| 602 | +
|
| 603 | +struct Foo { |
| 604 | + $0bar: bar::Bar, |
| 605 | +} |
| 606 | +"#, |
| 607 | + r#" |
| 608 | +mod bar; |
| 609 | +
|
| 610 | +struct Foo { |
| 611 | + bar: bar::Bar, |
| 612 | +} |
| 613 | +
|
| 614 | +impl Foo { |
| 615 | + $0pub fn test(self,b:bar::Bar) ->bar::Bar { |
| 616 | + self.bar.test(b) |
| 617 | + } |
| 618 | +} |
| 619 | +"#, |
| 620 | + ); |
| 621 | + } |
| 622 | + |
457 | 623 | #[test]
|
458 | 624 | fn test_generate_delegate_visibility() {
|
459 | 625 | check_assist_not_applicable(
|
|
0 commit comments