aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/add_missing_impl_members.rs123
-rw-r--r--crates/ra_assists/src/lib.rs1
2 files changed, 100 insertions, 24 deletions
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index 4435c4b5d..e13f54c4f 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -9,7 +9,35 @@ use ra_fmt::{leading_indent, reindent};
9 9
10use itertools::Itertools; 10use itertools::Itertools;
11 11
12pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 12enum AddMissingImplMembersMode {
13 DefaultMethodsOnly,
14 NoDefaultMethods,
15}
16
17pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
18 add_missing_impl_members_inner(
19 ctx,
20 AddMissingImplMembersMode::NoDefaultMethods,
21 "add_impl_missing_members",
22 "add missing impl members",
23 )
24}
25
26pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
27 add_missing_impl_members_inner(
28 ctx,
29 AddMissingImplMembersMode::DefaultMethodsOnly,
30 "add_impl_default_members",
31 "add impl default members",
32 )
33}
34
35fn add_missing_impl_members_inner(
36 mut ctx: AssistCtx<impl HirDatabase>,
37 mode: AddMissingImplMembersMode,
38 assist_id: &'static str,
39 label: &'static str,
40) -> Option<Assist> {
13 let impl_node = ctx.node_at_offset::<ast::ImplBlock>()?; 41 let impl_node = ctx.node_at_offset::<ast::ImplBlock>()?;
14 let impl_item_list = impl_node.item_list()?; 42 let impl_item_list = impl_node.item_list()?;
15 43
@@ -35,6 +63,10 @@ pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) ->
35 trait_fns 63 trait_fns
36 .into_iter() 64 .into_iter()
37 .filter(|t| def_name(t).is_some()) 65 .filter(|t| def_name(t).is_some())
66 .filter(|t| match mode {
67 AddMissingImplMembersMode::DefaultMethodsOnly => t.body().is_some(),
68 AddMissingImplMembersMode::NoDefaultMethods => t.body().is_none(),
69 })
38 .filter(|t| impl_fns.iter().all(|i| def_name(i) != def_name(t))) 70 .filter(|t| impl_fns.iter().all(|i| def_name(i) != def_name(t)))
39 .collect() 71 .collect()
40 }; 72 };
@@ -42,7 +74,7 @@ pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) ->
42 return None; 74 return None;
43 } 75 }
44 76
45 ctx.add_action(AssistId("add_impl_missing_members"), "add missing impl members", |edit| { 77 ctx.add_action(AssistId(assist_id), label, |edit| {
46 let (parent_indent, indent) = { 78 let (parent_indent, indent) = {
47 // FIXME: Find a way to get the indent already used in the file. 79 // FIXME: Find a way to get the indent already used in the file.
48 // Now, we copy the indent of first item or indent with 4 spaces relative to impl block 80 // Now, we copy the indent of first item or indent with 4 spaces relative to impl block
@@ -103,11 +135,13 @@ fn build_func_body(def: &ast::FnDef) -> String {
103 let mut buf = String::new(); 135 let mut buf = String::new();
104 136
105 for child in def.syntax().children() { 137 for child in def.syntax().children() {
106 if child.kind() == SyntaxKind::SEMI { 138 match (child.prev_sibling().map(|c| c.kind()), child.kind()) {
107 buf.push_str(" { unimplemented!() }") 139 (_, SyntaxKind::SEMI) => buf.push_str(" { unimplemented!() }"),
108 } else { 140 (_, SyntaxKind::ATTR) | (_, SyntaxKind::COMMENT) => {}
109 child.text().push_to(&mut buf); 141 (Some(SyntaxKind::ATTR), SyntaxKind::WHITESPACE)
110 } 142 | (Some(SyntaxKind::COMMENT), SyntaxKind::WHITESPACE) => {}
143 _ => child.text().push_to(&mut buf),
144 };
111 } 145 }
112 146
113 buf.trim_end().to_string() 147 buf.trim_end().to_string()
@@ -180,8 +214,7 @@ struct S;
180 214
181impl Foo for S { 215impl Foo for S {
182 fn bar(&self) {} 216 fn bar(&self) {}
183 fn foo(&self) { unimplemented!() } 217 fn foo(&self) { unimplemented!() }<|>
184 fn baz(&self) -> u32 { 42 }<|>
185}", 218}",
186 ); 219 );
187 } 220 }
@@ -193,7 +226,7 @@ impl Foo for S {
193 " 226 "
194trait Foo { fn foo(&self); } 227trait Foo { fn foo(&self); }
195struct S; 228struct S;
196impl Foo for S {<|>}", 229impl Foo for S { <|> }",
197 " 230 "
198trait Foo { fn foo(&self); } 231trait Foo { fn foo(&self); }
199struct S; 232struct S;
@@ -232,8 +265,8 @@ impl Foo for S { <|> }",
232 } 265 }
233 266
234 #[test] 267 #[test]
235 fn test_ignore_unnamed_trait_members() { 268 fn test_ignore_unnamed_trait_members_and_default_methods() {
236 check_assist( 269 check_assist_not_applicable(
237 add_missing_impl_members, 270 add_missing_impl_members,
238 " 271 "
239trait Foo { 272trait Foo {
@@ -242,15 +275,6 @@ trait Foo {
242} 275}
243struct S; 276struct S;
244impl Foo for S { <|> }", 277impl Foo for S { <|> }",
245 "
246trait Foo {
247 fn (arg: u32);
248 fn valid(some: u32) -> bool { false }
249}
250struct S;
251impl Foo for S {
252 fn valid(some: u32) -> bool { false }<|>
253}",
254 ) 278 )
255 } 279 }
256 280
@@ -260,7 +284,7 @@ impl Foo for S {
260 add_missing_impl_members, 284 add_missing_impl_members,
261 " 285 "
262trait Foo { 286trait Foo {
263 fn valid(some: u32) -> bool { false } 287 fn valid(some: u32) -> bool;
264} 288}
265struct S; 289struct S;
266 290
@@ -269,15 +293,66 @@ mod my_mod {
269}", 293}",
270 " 294 "
271trait Foo { 295trait Foo {
272 fn valid(some: u32) -> bool { false } 296 fn valid(some: u32) -> bool;
273} 297}
274struct S; 298struct S;
275 299
276mod my_mod { 300mod my_mod {
277 impl crate::Foo for S { 301 impl crate::Foo for S {
278 fn valid(some: u32) -> bool { false }<|> 302 fn valid(some: u32) -> bool { unimplemented!() }<|>
303 }
304}",
305 )
306 }
307
308 #[test]
309 fn test_with_docstring_and_attrs() {
310 check_assist(
311 add_missing_impl_members,
312 r#"
313#[doc(alias = "test alias")]
314trait Foo {
315 /// doc string
316 #[must_use]
317 fn foo(&self);
318}
319struct S;
320impl Foo for S {}<|>"#,
321 r#"
322#[doc(alias = "test alias")]
323trait Foo {
324 /// doc string
325 #[must_use]
326 fn foo(&self);
327}
328struct S;
329impl Foo for S {
330 fn foo(&self) { unimplemented!() }<|>
331}"#,
332 )
279 } 333 }
334
335 #[test]
336 fn test_default_methods() {
337 check_assist(
338 add_missing_default_members,
339 "
340trait Foo {
341 fn valid(some: u32) -> bool { false }
342 fn foo(some: u32) -> bool;
343}
344struct S;
345impl Foo for S { <|> }",
346 "
347trait Foo {
348 fn valid(some: u32) -> bool { false }
349 fn foo(some: u32) -> bool;
350}
351struct S;
352impl Foo for S {
353 fn valid(some: u32) -> bool { false }<|>
280}", 354}",
281 ) 355 )
282 } 356 }
357
283} 358}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 871b37f58..fc36e8cc9 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -112,6 +112,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
112 remove_dbg::remove_dbg, 112 remove_dbg::remove_dbg,
113 auto_import::auto_import, 113 auto_import::auto_import,
114 add_missing_impl_members::add_missing_impl_members, 114 add_missing_impl_members::add_missing_impl_members,
115 add_missing_impl_members::add_missing_default_members,
115 ] 116 ]
116} 117}
117 118