aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/add_custom_impl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/handlers/add_custom_impl.rs')
-rw-r--r--crates/ra_assists/src/handlers/add_custom_impl.rs65
1 files changed, 34 insertions, 31 deletions
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs
index 4ea26a550..fa70c8496 100644
--- a/crates/ra_assists/src/handlers/add_custom_impl.rs
+++ b/crates/ra_assists/src/handlers/add_custom_impl.rs
@@ -6,7 +6,10 @@ use ra_syntax::{
6}; 6};
7use stdx::SepBy; 7use stdx::SepBy;
8 8
9use crate::{Assist, AssistCtx, AssistId}; 9use crate::{
10 assist_context::{AssistContext, Assists},
11 AssistId,
12};
10 13
11// Assist: add_custom_impl 14// Assist: add_custom_impl
12// 15//
@@ -22,10 +25,10 @@ use crate::{Assist, AssistCtx, AssistId};
22// struct S; 25// struct S;
23// 26//
24// impl Debug for S { 27// impl Debug for S {
25// 28// $0
26// } 29// }
27// ``` 30// ```
28pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { 31pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
29 let input = ctx.find_node_at_offset::<ast::AttrInput>()?; 32 let input = ctx.find_node_at_offset::<ast::AttrInput>()?;
30 let attr = input.syntax().parent().and_then(ast::Attr::cast)?; 33 let attr = input.syntax().parent().and_then(ast::Attr::cast)?;
31 34
@@ -46,11 +49,10 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
46 let start_offset = annotated.syntax().parent()?.text_range().end(); 49 let start_offset = annotated.syntax().parent()?.text_range().end();
47 50
48 let label = 51 let label =
49 format!("Add custom impl '{}' for '{}'", trait_token.text().as_str(), annotated_name); 52 format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name);
50
51 ctx.add_assist(AssistId("add_custom_impl"), label, |edit| {
52 edit.target(attr.syntax().text_range());
53 53
54 let target = attr.syntax().text_range();
55 acc.add(AssistId("add_custom_impl"), label, target, |builder| {
54 let new_attr_input = input 56 let new_attr_input = input
55 .syntax() 57 .syntax()
56 .descendants_with_tokens() 58 .descendants_with_tokens()
@@ -61,20 +63,11 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
61 let has_more_derives = !new_attr_input.is_empty(); 63 let has_more_derives = !new_attr_input.is_empty();
62 let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string(); 64 let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string();
63 65
64 let mut buf = String::new(); 66 if has_more_derives {
65 buf.push_str("\n\nimpl "); 67 builder.replace(input.syntax().text_range(), new_attr_input);
66 buf.push_str(trait_token.text().as_str());
67 buf.push_str(" for ");
68 buf.push_str(annotated_name.as_str());
69 buf.push_str(" {\n");
70
71 let cursor_delta = if has_more_derives {
72 let delta = input.syntax().text_range().len() - TextSize::of(&new_attr_input);
73 edit.replace(input.syntax().text_range(), new_attr_input);
74 delta
75 } else { 68 } else {
76 let attr_range = attr.syntax().text_range(); 69 let attr_range = attr.syntax().text_range();
77 edit.delete(attr_range); 70 builder.delete(attr_range);
78 71
79 let line_break_range = attr 72 let line_break_range = attr
80 .syntax() 73 .syntax()
@@ -82,20 +75,30 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
82 .filter(|t| t.kind() == WHITESPACE) 75 .filter(|t| t.kind() == WHITESPACE)
83 .map(|t| t.text_range()) 76 .map(|t| t.text_range())
84 .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0))); 77 .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0)));
85 edit.delete(line_break_range); 78 builder.delete(line_break_range);
86 79 }
87 attr_range.len() + line_break_range.len() 80
88 }; 81 match ctx.config.snippet_cap {
89 82 Some(cap) => {
90 edit.set_cursor(start_offset + TextSize::of(&buf) - cursor_delta); 83 builder.insert_snippet(
91 buf.push_str("\n}"); 84 cap,
92 edit.insert(start_offset, buf); 85 start_offset,
86 format!("\n\nimpl {} for {} {{\n $0\n}}", trait_token, annotated_name),
87 );
88 }
89 None => {
90 builder.insert(
91 start_offset,
92 format!("\n\nimpl {} for {} {{\n\n}}", trait_token, annotated_name),
93 );
94 }
95 }
93 }) 96 })
94} 97}
95 98
96#[cfg(test)] 99#[cfg(test)]
97mod tests { 100mod tests {
98 use crate::helpers::{check_assist, check_assist_not_applicable}; 101 use crate::tests::{check_assist, check_assist_not_applicable};
99 102
100 use super::*; 103 use super::*;
101 104
@@ -115,7 +118,7 @@ struct Foo {
115} 118}
116 119
117impl Debug for Foo { 120impl Debug for Foo {
118<|> 121 $0
119} 122}
120 ", 123 ",
121 ) 124 )
@@ -137,7 +140,7 @@ pub struct Foo {
137} 140}
138 141
139impl Debug for Foo { 142impl Debug for Foo {
140<|> 143 $0
141} 144}
142 ", 145 ",
143 ) 146 )
@@ -156,7 +159,7 @@ struct Foo {}
156struct Foo {} 159struct Foo {}
157 160
158impl Debug for Foo { 161impl Debug for Foo {
159<|> 162 $0
160} 163}
161 ", 164 ",
162 ) 165 )