aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/add_derive.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/handlers/add_derive.rs')
-rw-r--r--crates/ra_assists/src/handlers/add_derive.rs37
1 files changed, 22 insertions, 15 deletions
diff --git a/crates/ra_assists/src/handlers/add_derive.rs b/crates/ra_assists/src/handlers/add_derive.rs
index 6254eb7c4..b123b8498 100644
--- a/crates/ra_assists/src/handlers/add_derive.rs
+++ b/crates/ra_assists/src/handlers/add_derive.rs
@@ -4,7 +4,7 @@ use ra_syntax::{
4 TextSize, 4 TextSize,
5}; 5};
6 6
7use crate::{Assist, AssistCtx, AssistId}; 7use crate::{AssistContext, AssistId, Assists};
8 8
9// Assist: add_derive 9// Assist: add_derive
10// 10//
@@ -18,31 +18,37 @@ use crate::{Assist, AssistCtx, AssistId};
18// ``` 18// ```
19// -> 19// ->
20// ``` 20// ```
21// #[derive()] 21// #[derive($0)]
22// struct Point { 22// struct Point {
23// x: u32, 23// x: u32,
24// y: u32, 24// y: u32,
25// } 25// }
26// ``` 26// ```
27pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> { 27pub(crate) fn add_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
28 let cap = ctx.config.snippet_cap?;
28 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; 29 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
29 let node_start = derive_insertion_offset(&nominal)?; 30 let node_start = derive_insertion_offset(&nominal)?;
30 ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| { 31 let target = nominal.syntax().text_range();
32 acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |builder| {
31 let derive_attr = nominal 33 let derive_attr = nominal
32 .attrs() 34 .attrs()
33 .filter_map(|x| x.as_simple_call()) 35 .filter_map(|x| x.as_simple_call())
34 .filter(|(name, _arg)| name == "derive") 36 .filter(|(name, _arg)| name == "derive")
35 .map(|(_name, arg)| arg) 37 .map(|(_name, arg)| arg)
36 .next(); 38 .next();
37 let offset = match derive_attr { 39 match derive_attr {
38 None => { 40 None => {
39 edit.insert(node_start, "#[derive()]\n"); 41 builder.insert_snippet(cap, node_start, "#[derive($0)]\n");
40 node_start + TextSize::of("#[derive(") 42 }
43 Some(tt) => {
44 // Just move the cursor.
45 builder.insert_snippet(
46 cap,
47 tt.syntax().text_range().end() - TextSize::of(')'),
48 "$0",
49 )
41 } 50 }
42 Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'),
43 }; 51 };
44 edit.target(nominal.syntax().text_range());
45 edit.set_cursor(offset)
46 }) 52 })
47} 53}
48 54
@@ -57,20 +63,21 @@ fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextSize> {
57 63
58#[cfg(test)] 64#[cfg(test)]
59mod tests { 65mod tests {
66 use crate::tests::{check_assist, check_assist_target};
67
60 use super::*; 68 use super::*;
61 use crate::helpers::{check_assist, check_assist_target};
62 69
63 #[test] 70 #[test]
64 fn add_derive_new() { 71 fn add_derive_new() {
65 check_assist( 72 check_assist(
66 add_derive, 73 add_derive,
67 "struct Foo { a: i32, <|>}", 74 "struct Foo { a: i32, <|>}",
68 "#[derive(<|>)]\nstruct Foo { a: i32, }", 75 "#[derive($0)]\nstruct Foo { a: i32, }",
69 ); 76 );
70 check_assist( 77 check_assist(
71 add_derive, 78 add_derive,
72 "struct Foo { <|> a: i32, }", 79 "struct Foo { <|> a: i32, }",
73 "#[derive(<|>)]\nstruct Foo { a: i32, }", 80 "#[derive($0)]\nstruct Foo { a: i32, }",
74 ); 81 );
75 } 82 }
76 83
@@ -79,7 +86,7 @@ mod tests {
79 check_assist( 86 check_assist(
80 add_derive, 87 add_derive,
81 "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", 88 "#[derive(Clone)]\nstruct Foo { a: i32<|>, }",
82 "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", 89 "#[derive(Clone$0)]\nstruct Foo { a: i32, }",
83 ); 90 );
84 } 91 }
85 92
@@ -95,7 +102,7 @@ struct Foo { a: i32<|>, }
95 " 102 "
96/// `Foo` is a pretty important struct. 103/// `Foo` is a pretty important struct.
97/// It does stuff. 104/// It does stuff.
98#[derive(<|>)] 105#[derive($0)]
99struct Foo { a: i32, } 106struct Foo { a: i32, }
100 ", 107 ",
101 ); 108 );