aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
authorIgor Matuszewski <[email protected]>2019-03-16 22:19:14 +0000
committerIgor Matuszewski <[email protected]>2019-03-16 22:19:14 +0000
commit5b0b87f8deded258585d161c3077280e7d8112e9 (patch)
treeaf2c6431ba49d31841b28652e828ffeed38d40a7 /crates/ra_assists
parent2f36f47dab59886f2f82252f427c4a3d3ee2c83b (diff)
Provide assist when cursor is immediately outside impl item block
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/add_missing_impl_members.rs32
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`.
14pub(crate) fn resolve_target_trait_def( 14fn 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
28pub(crate) fn build_func_body(def: &ast::FnDef) -> String { 28fn 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
42pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 42pub(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 "
213trait Foo { fn foo(&self); } 211trait Foo { fn foo(&self); }
214struct S; 212struct S;
215impl Foo for S {}<|>", 213impl Foo for S {}<|>",
214 "
215trait Foo { fn foo(&self); }
216struct S;
217impl Foo for S {
218 fn foo(&self) { unimplemented!() }<|>
219}",
216 ) 220 )
217 } 221 }
218 222