diff options
Diffstat (limited to 'crates/assists/src')
-rw-r--r-- | crates/assists/src/handlers/replace_impl_trait_with_generic.rs | 110 |
1 files changed, 102 insertions, 8 deletions
diff --git a/crates/assists/src/handlers/replace_impl_trait_with_generic.rs b/crates/assists/src/handlers/replace_impl_trait_with_generic.rs index 8af2d16dd..5b0d5d971 100644 --- a/crates/assists/src/handlers/replace_impl_trait_with_generic.rs +++ b/crates/assists/src/handlers/replace_impl_trait_with_generic.rs | |||
@@ -13,9 +13,6 @@ pub(crate) fn replace_impl_trait_with_generic( | |||
13 | let type_param = type_impl_trait.syntax().parent().and_then(ast::Param::cast)?; | 13 | let type_param = type_impl_trait.syntax().parent().and_then(ast::Param::cast)?; |
14 | let type_fn = type_param.syntax().ancestors().nth(2).and_then(ast::Fn::cast)?; | 14 | let type_fn = type_param.syntax().ancestors().nth(2).and_then(ast::Fn::cast)?; |
15 | 15 | ||
16 | let generic_param_list = | ||
17 | type_fn.generic_param_list().unwrap_or_else(|| make::generic_param_list(None)); | ||
18 | |||
19 | let impl_trait_ty = type_impl_trait | 16 | let impl_trait_ty = type_impl_trait |
20 | .syntax() | 17 | .syntax() |
21 | .descendants() | 18 | .descendants() |
@@ -31,11 +28,16 @@ pub(crate) fn replace_impl_trait_with_generic( | |||
31 | target, | 28 | target, |
32 | |edit| { | 29 | |edit| { |
33 | let generic_letter = impl_trait_ty[..1].to_string(); | 30 | let generic_letter = impl_trait_ty[..1].to_string(); |
34 | edit.replace_ast::<ast::Type>(type_impl_trait.into(), make::ty(&generic_letter)); | ||
35 | 31 | ||
36 | let new_params = generic_param_list | 32 | let generic_param_list = type_fn |
37 | .append_param(make::generic_param(generic_letter, Some(impl_trait_ty))); | 33 | .generic_param_list() |
38 | let new_type_fn = type_fn.replace_descendant(generic_param_list, new_params); | 34 | .unwrap_or_else(|| make::generic_param_list(None)) |
35 | .append_param(make::generic_param(generic_letter.clone(), Some(impl_trait_ty))); | ||
36 | |||
37 | let new_type_fn = type_fn | ||
38 | .replace_descendant::<ast::Type>(type_impl_trait.into(), make::ty(&generic_letter)) | ||
39 | .with_generic_params(generic_param_list); | ||
40 | |||
39 | edit.replace_ast(type_fn.clone(), new_type_fn); | 41 | edit.replace_ast(type_fn.clone(), new_type_fn); |
40 | }, | 42 | }, |
41 | ) | 43 | ) |
@@ -48,7 +50,7 @@ mod tests { | |||
48 | use crate::tests::check_assist; | 50 | use crate::tests::check_assist; |
49 | 51 | ||
50 | #[test] | 52 | #[test] |
51 | fn replace_with_generic_params() { | 53 | fn replace_impl_trait_with_generic_params() { |
52 | check_assist( | 54 | check_assist( |
53 | replace_impl_trait_with_generic, | 55 | replace_impl_trait_with_generic, |
54 | r#" | 56 | r#" |
@@ -59,4 +61,96 @@ mod tests { | |||
59 | "#, | 61 | "#, |
60 | ); | 62 | ); |
61 | } | 63 | } |
64 | |||
65 | #[test] | ||
66 | fn replace_impl_trait_without_generic_params() { | ||
67 | check_assist( | ||
68 | replace_impl_trait_with_generic, | ||
69 | r#" | ||
70 | fn foo(bar: <|>impl Bar) {} | ||
71 | "#, | ||
72 | r#" | ||
73 | fn foo<B: Bar>(bar: B) {} | ||
74 | "#, | ||
75 | ); | ||
76 | } | ||
77 | |||
78 | #[test] | ||
79 | fn replace_two_impl_trait_with_generic_params() { | ||
80 | check_assist( | ||
81 | replace_impl_trait_with_generic, | ||
82 | r#" | ||
83 | fn foo<G>(foo: impl Foo, bar: <|>impl Bar) {} | ||
84 | "#, | ||
85 | r#" | ||
86 | fn foo<G, B: Bar>(foo: impl Foo, bar: B) {} | ||
87 | "#, | ||
88 | ); | ||
89 | } | ||
90 | |||
91 | #[test] | ||
92 | fn replace_impl_trait_with_empty_generic_params() { | ||
93 | check_assist( | ||
94 | replace_impl_trait_with_generic, | ||
95 | r#" | ||
96 | fn foo<>(bar: <|>impl Bar) {} | ||
97 | "#, | ||
98 | r#" | ||
99 | fn foo<B: Bar>(bar: B) {} | ||
100 | "#, | ||
101 | ); | ||
102 | } | ||
103 | |||
104 | #[test] | ||
105 | fn replace_impl_trait_with_empty_multiline_generic_params() { | ||
106 | // FIXME: It would be more correct to place the generic parameter | ||
107 | // on the next line after the left angle. | ||
108 | check_assist( | ||
109 | replace_impl_trait_with_generic, | ||
110 | r#" | ||
111 | fn foo< | ||
112 | >(bar: <|>impl Bar) {} | ||
113 | "#, | ||
114 | r#" | ||
115 | fn foo<B: Bar, | ||
116 | >(bar: B) {} | ||
117 | "#, | ||
118 | ); | ||
119 | } | ||
120 | |||
121 | #[test] | ||
122 | #[ignore = "This case is very rare but there is no simple solutions to fix it."] | ||
123 | fn replace_impl_trait_with_exist_generic_letter() { | ||
124 | check_assist( | ||
125 | replace_impl_trait_with_generic, | ||
126 | r#" | ||
127 | fn foo<B>(bar: <|>impl Bar) {} | ||
128 | "#, | ||
129 | r#" | ||
130 | fn foo<B, C: Bar>(bar: C) {} | ||
131 | "#, | ||
132 | ); | ||
133 | } | ||
134 | |||
135 | #[test] | ||
136 | fn replace_impl_trait_with_multiline_generic_params() { | ||
137 | check_assist( | ||
138 | replace_impl_trait_with_generic, | ||
139 | r#" | ||
140 | fn foo< | ||
141 | G: Foo, | ||
142 | F, | ||
143 | H, | ||
144 | >(bar: <|>impl Bar) {} | ||
145 | "#, | ||
146 | r#" | ||
147 | fn foo< | ||
148 | G: Foo, | ||
149 | F, | ||
150 | H, | ||
151 | B: Bar, | ||
152 | >(bar: B) {} | ||
153 | "#, | ||
154 | ); | ||
155 | } | ||
62 | } | 156 | } |