summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
diff options
context:
space:
mode:
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.rs216
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,