diff options
Diffstat (limited to 'crates/assists/src/handlers/generate_new.rs')
-rw-r--r-- | crates/assists/src/handlers/generate_new.rs | 69 |
1 files changed, 15 insertions, 54 deletions
diff --git a/crates/assists/src/handlers/generate_new.rs b/crates/assists/src/handlers/generate_new.rs index a9203d33f..c29077225 100644 --- a/crates/assists/src/handlers/generate_new.rs +++ b/crates/assists/src/handlers/generate_new.rs | |||
@@ -1,12 +1,10 @@ | |||
1 | use ast::Adt; | ||
1 | use itertools::Itertools; | 2 | use itertools::Itertools; |
2 | use stdx::format_to; | 3 | use stdx::format_to; |
3 | use syntax::{ | 4 | use syntax::ast::{self, AstNode, NameOwner, StructKind, VisibilityOwner}; |
4 | ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner}, | ||
5 | SmolStr, | ||
6 | }; | ||
7 | 5 | ||
8 | use crate::{ | 6 | use crate::{ |
9 | utils::{find_impl_block, find_struct_impl}, | 7 | utils::{find_impl_block, find_struct_impl, generate_impl_text}, |
10 | AssistContext, AssistId, AssistKind, Assists, | 8 | AssistContext, AssistId, AssistKind, Assists, |
11 | }; | 9 | }; |
12 | 10 | ||
@@ -28,7 +26,6 @@ use crate::{ | |||
28 | // impl<T: Clone> Ctx<T> { | 26 | // impl<T: Clone> Ctx<T> { |
29 | // fn $0new(data: T) -> Self { Self { data } } | 27 | // fn $0new(data: T) -> Self { Self { data } } |
30 | // } | 28 | // } |
31 | // | ||
32 | // ``` | 29 | // ``` |
33 | pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 30 | pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
34 | let strukt = ctx.find_node_at_offset::<ast::Struct>()?; | 31 | let strukt = ctx.find_node_at_offset::<ast::Struct>()?; |
@@ -40,7 +37,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
40 | }; | 37 | }; |
41 | 38 | ||
42 | // Return early if we've found an existing new fn | 39 | // Return early if we've found an existing new fn |
43 | let impl_def = find_struct_impl(&ctx, &ast::Adt::Struct(strukt.clone()), "new")?; | 40 | let impl_def = find_struct_impl(&ctx, &Adt::Struct(strukt.clone()), "new")?; |
44 | 41 | ||
45 | let target = strukt.syntax().text_range(); | 42 | let target = strukt.syntax().text_range(); |
46 | acc.add(AssistId("generate_new", AssistKind::Generate), "Generate `new`", target, |builder| { | 43 | acc.add(AssistId("generate_new", AssistKind::Generate), "Generate `new`", target, |builder| { |
@@ -63,7 +60,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
63 | let start_offset = impl_def | 60 | let start_offset = impl_def |
64 | .and_then(|impl_def| find_impl_block(impl_def, &mut buf)) | 61 | .and_then(|impl_def| find_impl_block(impl_def, &mut buf)) |
65 | .unwrap_or_else(|| { | 62 | .unwrap_or_else(|| { |
66 | buf = generate_impl_text(&strukt, &buf); | 63 | buf = generate_impl_text(&Adt::Struct(strukt.clone()), &buf); |
67 | strukt.syntax().text_range().end() | 64 | strukt.syntax().text_range().end() |
68 | }); | 65 | }); |
69 | 66 | ||
@@ -77,32 +74,6 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
77 | }) | 74 | }) |
78 | } | 75 | } |
79 | 76 | ||
80 | // Generates the surrounding `impl Type { <code> }` including type and lifetime | ||
81 | // parameters | ||
82 | fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String { | ||
83 | let type_params = strukt.generic_param_list(); | ||
84 | let mut buf = String::with_capacity(code.len()); | ||
85 | buf.push_str("\n\nimpl"); | ||
86 | if let Some(type_params) = &type_params { | ||
87 | format_to!(buf, "{}", type_params.syntax()); | ||
88 | } | ||
89 | buf.push(' '); | ||
90 | buf.push_str(strukt.name().unwrap().text()); | ||
91 | if let Some(type_params) = type_params { | ||
92 | let lifetime_params = type_params | ||
93 | .lifetime_params() | ||
94 | .filter_map(|it| it.lifetime()) | ||
95 | .map(|it| SmolStr::from(it.text())); | ||
96 | let type_params = | ||
97 | type_params.type_params().filter_map(|it| it.name()).map(|it| SmolStr::from(it.text())); | ||
98 | format_to!(buf, "<{}>", lifetime_params.chain(type_params).format(", ")) | ||
99 | } | ||
100 | |||
101 | format_to!(buf, " {{\n{}\n}}\n", code); | ||
102 | |||
103 | buf | ||
104 | } | ||
105 | |||
106 | #[cfg(test)] | 77 | #[cfg(test)] |
107 | mod tests { | 78 | mod tests { |
108 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; | 79 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; |
@@ -120,8 +91,7 @@ mod tests { | |||
120 | 91 | ||
121 | impl Foo { | 92 | impl Foo { |
122 | fn $0new() -> Self { Self { } } | 93 | fn $0new() -> Self { Self { } } |
123 | } | 94 | }", |
124 | ", | ||
125 | ); | 95 | ); |
126 | check_assist( | 96 | check_assist( |
127 | generate_new, | 97 | generate_new, |
@@ -130,8 +100,7 @@ impl Foo { | |||
130 | 100 | ||
131 | impl<T: Clone> Foo<T> { | 101 | impl<T: Clone> Foo<T> { |
132 | fn $0new() -> Self { Self { } } | 102 | fn $0new() -> Self { Self { } } |
133 | } | 103 | }", |
134 | ", | ||
135 | ); | 104 | ); |
136 | check_assist( | 105 | check_assist( |
137 | generate_new, | 106 | generate_new, |
@@ -140,8 +109,7 @@ impl<T: Clone> Foo<T> { | |||
140 | 109 | ||
141 | impl<'a, T: Foo<'a>> Foo<'a, T> { | 110 | impl<'a, T: Foo<'a>> Foo<'a, T> { |
142 | fn $0new() -> Self { Self { } } | 111 | fn $0new() -> Self { Self { } } |
143 | } | 112 | }", |
144 | ", | ||
145 | ); | 113 | ); |
146 | check_assist( | 114 | check_assist( |
147 | generate_new, | 115 | generate_new, |
@@ -150,8 +118,7 @@ impl<'a, T: Foo<'a>> Foo<'a, T> { | |||
150 | 118 | ||
151 | impl Foo { | 119 | impl Foo { |
152 | fn $0new(baz: String) -> Self { Self { baz } } | 120 | fn $0new(baz: String) -> Self { Self { baz } } |
153 | } | 121 | }", |
154 | ", | ||
155 | ); | 122 | ); |
156 | check_assist( | 123 | check_assist( |
157 | generate_new, | 124 | generate_new, |
@@ -160,8 +127,7 @@ impl Foo { | |||
160 | 127 | ||
161 | impl Foo { | 128 | impl Foo { |
162 | fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } } | 129 | fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } } |
163 | } | 130 | }", |
164 | ", | ||
165 | ); | 131 | ); |
166 | 132 | ||
167 | // Check that visibility modifiers don't get brought in for fields | 133 | // Check that visibility modifiers don't get brought in for fields |
@@ -172,8 +138,7 @@ impl Foo { | |||
172 | 138 | ||
173 | impl Foo { | 139 | impl Foo { |
174 | fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } } | 140 | fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } } |
175 | } | 141 | }", |
176 | ", | ||
177 | ); | 142 | ); |
178 | 143 | ||
179 | // Check that it reuses existing impls | 144 | // Check that it reuses existing impls |
@@ -240,8 +205,7 @@ impl Foo { | |||
240 | 205 | ||
241 | impl Foo { | 206 | impl Foo { |
242 | pub fn $0new() -> Self { Self { } } | 207 | pub fn $0new() -> Self { Self { } } |
243 | } | 208 | }", |
244 | ", | ||
245 | ); | 209 | ); |
246 | check_assist( | 210 | check_assist( |
247 | generate_new, | 211 | generate_new, |
@@ -250,8 +214,7 @@ impl Foo { | |||
250 | 214 | ||
251 | impl Foo { | 215 | impl Foo { |
252 | pub(crate) fn $0new() -> Self { Self { } } | 216 | pub(crate) fn $0new() -> Self { Self { } } |
253 | } | 217 | }", |
254 | ", | ||
255 | ); | 218 | ); |
256 | } | 219 | } |
257 | 220 | ||
@@ -322,8 +285,7 @@ impl<T> Source<T> { | |||
322 | pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { | 285 | pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { |
323 | Source { file_id: self.file_id, ast: f(self.ast) } | 286 | Source { file_id: self.file_id, ast: f(self.ast) } |
324 | } | 287 | } |
325 | } | 288 | }"##, |
326 | "##, | ||
327 | r##" | 289 | r##" |
328 | pub struct AstId<N: AstNode> { | 290 | pub struct AstId<N: AstNode> { |
329 | file_id: HirFileId, | 291 | file_id: HirFileId, |
@@ -347,8 +309,7 @@ impl<T> Source<T> { | |||
347 | pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { | 309 | pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { |
348 | Source { file_id: self.file_id, ast: f(self.ast) } | 310 | Source { file_id: self.file_id, ast: f(self.ast) } |
349 | } | 311 | } |
350 | } | 312 | }"##, |
351 | "##, | ||
352 | ); | 313 | ); |
353 | } | 314 | } |
354 | } | 315 | } |