diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs | 216 |
1 files changed, 213 insertions, 3 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs index bbac0a26e..db1e0ceae 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs @@ -1,6 +1,7 @@ use std::collections::HashSet; -use hir::{self, HasCrate, HasSource, HasVisibility}; +use hir::{self, HasCrate, HasVisibility}; +use ide_db::path_transform::PathTransform; use syntax::{ ast::{ self, edit_in_place::Indent, make, AstNode, HasGenericParams, HasName, HasVisibility as _, @@ -105,7 +106,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' target, |edit| { // Create the function - let method_source = match method.source(ctx.db()) { + let method_source = match ctx.sema.source(method) { Some(source) => source.value, None => return, }; @@ -130,7 +131,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' vis, fn_name, type_params, - None, + method_source.where_clause(), params, body, ret_type, @@ -183,6 +184,12 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<' let assoc_items = impl_def.get_or_create_assoc_item_list(); assoc_items.add_item(f.clone().into()); + if let Some((target, source)) = + ctx.sema.scope(strukt.syntax()).zip(ctx.sema.scope(method_source.syntax())) + { + PathTransform::generic_transformation(&target, &source).apply(f.syntax()); + } + if let Some(cap) = ctx.config.snippet_cap { edit.add_tabstop_before(cap, f) } @@ -455,6 +462,209 @@ impl Person { } #[test] + fn test_preserve_where_clause() { + check_assist( + generate_delegate_methods, + r#" +struct Inner<T>(T); +impl<T> Inner<T> { + fn get(&self) -> T + where + T: Copy, + T: PartialEq, + { + self.0 + } +} + +struct Struct<T> { + $0field: Inner<T>, +} +"#, + r#" +struct Inner<T>(T); +impl<T> Inner<T> { + fn get(&self) -> T + where + T: Copy, + T: PartialEq, + { + self.0 + } +} + +struct Struct<T> { + field: Inner<T>, +} + +impl<T> Struct<T> { + $0fn get(&self) -> T where + T: Copy, + T: PartialEq, { + self.field.get() + } +} +"#, + ); + } + + #[test] + fn test_fixes_basic_self_references() { + check_assist( + generate_delegate_methods, + r#" +struct Foo { + field: $0Bar, +} + +struct Bar; + +impl Bar { + fn bar(&self, other: Self) -> Self { + other + } +} +"#, + r#" +struct Foo { + field: Bar, +} + +impl Foo { + $0fn bar(&self, other: Bar) -> Bar { + self.field.bar(other) + } +} + +struct Bar; + +impl Bar { + fn bar(&self, other: Self) -> Self { + other + } +} +"#, + ); + } + + #[test] + fn test_fixes_nested_self_references() { + check_assist( + generate_delegate_methods, + r#" +struct Foo { + field: $0Bar, +} + +struct Bar; + +impl Bar { + fn bar(&mut self, a: (Self, [Self; 4]), b: Vec<Self>) {} +} +"#, + r#" +struct Foo { + field: Bar, +} + +impl Foo { + $0fn bar(&mut self, a: (Bar, [Bar; 4]), b: Vec<Bar>) { + self.field.bar(a, b) + } +} + +struct Bar; + +impl Bar { + fn bar(&mut self, a: (Self, [Self; 4]), b: Vec<Self>) {} +} +"#, + ); + } + + #[test] + fn test_fixes_self_references_with_lifetimes_and_generics() { + check_assist( + generate_delegate_methods, + r#" +struct Foo<'a, T> { + $0field: Bar<'a, T>, +} + +struct Bar<'a, T>(&'a T); + +impl<'a, T> Bar<'a, T> { + fn bar(self, mut b: Vec<&'a Self>) -> &'a Self { + b.pop().unwrap() + } +} +"#, + r#" +struct Foo<'a, T> { + field: Bar<'a, T>, +} + +impl<'a, T> Foo<'a, T> { + $0fn bar(self, mut b: Vec<&'a Bar<'_, T>>) -> &'a Bar<'_, T> { + self.field.bar(b) + } +} + +struct Bar<'a, T>(&'a T); + +impl<'a, T> Bar<'a, T> { + fn bar(self, mut b: Vec<&'a Self>) -> &'a Self { + b.pop().unwrap() + } +} +"#, + ); + } + + #[test] + fn test_fixes_self_references_across_macros() { + check_assist( + generate_delegate_methods, + r#" +//- /bar.rs +macro_rules! test_method { + () => { + pub fn test(self, b: Bar) -> Self { + self + } + }; +} + +pub struct Bar; + +impl Bar { + test_method!(); +} + +//- /main.rs +mod bar; + +struct Foo { + $0bar: bar::Bar, +} +"#, + r#" +mod bar; + +struct Foo { + bar: bar::Bar, +} + +impl Foo { + $0pub fn test(self,b:bar::Bar) ->bar::Bar { + self.bar.test(b) + } +} +"#, + ); + } + + #[test] fn test_generate_delegate_visibility() { check_assist_not_applicable( generate_delegate_methods, |