diff options
author | Igor Matuszewski <[email protected]> | 2019-03-16 22:19:14 +0000 |
---|---|---|
committer | Igor Matuszewski <[email protected]> | 2019-03-16 22:19:14 +0000 |
commit | 5b0b87f8deded258585d161c3077280e7d8112e9 (patch) | |
tree | af2c6431ba49d31841b28652e828ffeed38d40a7 /crates | |
parent | 2f36f47dab59886f2f82252f427c4a3d3ee2c83b (diff) |
Provide assist when cursor is immediately outside impl item block
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/add_missing_impl_members.rs | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs index 567fc9586..96dde3c4b 100644 --- a/crates/ra_assists/src/add_missing_impl_members.rs +++ b/crates/ra_assists/src/add_missing_impl_members.rs | |||
@@ -11,7 +11,7 @@ use itertools::Itertools; | |||
11 | 11 | ||
12 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being | 12 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being |
13 | /// implemented) to a `ast::TraitDef`. | 13 | /// implemented) to a `ast::TraitDef`. |
14 | pub(crate) fn resolve_target_trait_def( | 14 | fn resolve_target_trait_def( |
15 | db: &impl HirDatabase, | 15 | db: &impl HirDatabase, |
16 | resolver: &Resolver, | 16 | resolver: &Resolver, |
17 | impl_block: &ast::ImplBlock, | 17 | impl_block: &ast::ImplBlock, |
@@ -25,7 +25,7 @@ pub(crate) fn resolve_target_trait_def( | |||
25 | } | 25 | } |
26 | } | 26 | } |
27 | 27 | ||
28 | pub(crate) fn build_func_body(def: &ast::FnDef) -> String { | 28 | fn build_func_body(def: &ast::FnDef) -> String { |
29 | let mut buf = String::new(); | 29 | let mut buf = String::new(); |
30 | 30 | ||
31 | for child in def.syntax().children() { | 31 | for child in def.syntax().children() { |
@@ -40,17 +40,12 @@ pub(crate) fn build_func_body(def: &ast::FnDef) -> String { | |||
40 | } | 40 | } |
41 | 41 | ||
42 | pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 42 | pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
43 | let node = ctx.covering_node(); | 43 | let impl_node = ctx.node_at_offset::<ast::ImplBlock>()?; |
44 | let impl_node = node.ancestors().find_map(ast::ImplBlock::cast)?; | ||
45 | let impl_item_list = impl_node.item_list()?; | 44 | let impl_item_list = impl_node.item_list()?; |
46 | // Don't offer the assist when cursor is at the end, outside the block itself. | ||
47 | let cursor_range = TextRange::from_to(node.range().end(), node.range().end()); | ||
48 | if node.range().end() == impl_node.syntax().range().end() { | ||
49 | return None; | ||
50 | } | ||
51 | 45 | ||
52 | let trait_def = { | 46 | let trait_def = { |
53 | let position = FilePosition { file_id: ctx.frange.file_id, offset: cursor_range.end() }; | 47 | let file_id = ctx.frange.file_id; |
48 | let position = FilePosition { file_id, offset: impl_node.syntax().range().start() }; | ||
54 | let resolver = hir::source_binder::resolver_for_position(ctx.db, position); | 49 | let resolver = hir::source_binder::resolver_for_position(ctx.db, position); |
55 | 50 | ||
56 | resolve_target_trait_def(ctx.db, &resolver, impl_node)? | 51 | resolve_target_trait_def(ctx.db, &resolver, impl_node)? |
@@ -94,10 +89,13 @@ pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) -> | |||
94 | }; | 89 | }; |
95 | 90 | ||
96 | let changed_range = { | 91 | let changed_range = { |
97 | let last_whitespace = impl_item_list.syntax().children(); | 92 | let children = impl_item_list.syntax().children(); |
98 | let last_whitespace = last_whitespace.filter_map(ast::Whitespace::cast).last(); | 93 | let last_whitespace = children.filter_map(ast::Whitespace::cast).last(); |
99 | 94 | ||
100 | last_whitespace.map(|w| w.syntax().range()).unwrap_or(cursor_range) | 95 | last_whitespace.map(|w| w.syntax().range()).unwrap_or_else(|| { |
96 | let in_brackets = impl_item_list.syntax().range().end() - TextUnit::of_str("}"); | ||
97 | TextRange::from_to(in_brackets, in_brackets) | ||
98 | }) | ||
101 | }; | 99 | }; |
102 | 100 | ||
103 | let func_bodies = format!("\n{}", missing_fns.into_iter().map(build_func_body).join("\n")); | 101 | let func_bodies = format!("\n{}", missing_fns.into_iter().map(build_func_body).join("\n")); |
@@ -207,12 +205,18 @@ impl Foo for S { | |||
207 | 205 | ||
208 | #[test] | 206 | #[test] |
209 | fn test_cursor_after_empty_impl_block() { | 207 | fn test_cursor_after_empty_impl_block() { |
210 | check_assist_not_applicable( | 208 | check_assist( |
211 | add_missing_impl_members, | 209 | add_missing_impl_members, |
212 | " | 210 | " |
213 | trait Foo { fn foo(&self); } | 211 | trait Foo { fn foo(&self); } |
214 | struct S; | 212 | struct S; |
215 | impl Foo for S {}<|>", | 213 | impl Foo for S {}<|>", |
214 | " | ||
215 | trait Foo { fn foo(&self); } | ||
216 | struct S; | ||
217 | impl Foo for S { | ||
218 | fn foo(&self) { unimplemented!() }<|> | ||
219 | }", | ||
216 | ) | 220 | ) |
217 | } | 221 | } |
218 | 222 | ||