diff options
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r-- | crates/ra_editor/src/code_actions.rs | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs index 0139b19d3..37e963bbd 100644 --- a/crates/ra_editor/src/code_actions.rs +++ b/crates/ra_editor/src/code_actions.rs | |||
@@ -4,7 +4,7 @@ use ra_syntax::{ | |||
4 | algo::{find_covering_node, find_leaf_at_offset}, | 4 | algo::{find_covering_node, find_leaf_at_offset}, |
5 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, | 5 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, |
6 | Direction, SourceFileNode, | 6 | Direction, SourceFileNode, |
7 | SyntaxKind::{COMMA, WHITESPACE}, | 7 | SyntaxKind::{COMMA, WHITESPACE, COMMENT}, |
8 | SyntaxNodeRef, TextRange, TextUnit, | 8 | SyntaxNodeRef, TextRange, TextUnit, |
9 | }; | 9 | }; |
10 | 10 | ||
@@ -41,7 +41,8 @@ pub fn add_derive<'a>( | |||
41 | offset: TextUnit, | 41 | offset: TextUnit, |
42 | ) -> Option<impl FnOnce() -> LocalEdit + 'a> { | 42 | ) -> Option<impl FnOnce() -> LocalEdit + 'a> { |
43 | let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; | 43 | let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; |
44 | Some(move || { | 44 | let node_start = derive_insertion_offset(nominal)?; |
45 | return Some(move || { | ||
45 | let derive_attr = nominal | 46 | let derive_attr = nominal |
46 | .attrs() | 47 | .attrs() |
47 | .filter_map(|x| x.as_call()) | 48 | .filter_map(|x| x.as_call()) |
@@ -51,7 +52,6 @@ pub fn add_derive<'a>( | |||
51 | let mut edit = EditBuilder::new(); | 52 | let mut edit = EditBuilder::new(); |
52 | let offset = match derive_attr { | 53 | let offset = match derive_attr { |
53 | None => { | 54 | None => { |
54 | let node_start = nominal.syntax().range().start(); | ||
55 | edit.insert(node_start, "#[derive()]\n".to_string()); | 55 | edit.insert(node_start, "#[derive()]\n".to_string()); |
56 | node_start + TextUnit::of_str("#[derive(") | 56 | node_start + TextUnit::of_str("#[derive(") |
57 | } | 57 | } |
@@ -61,7 +61,16 @@ pub fn add_derive<'a>( | |||
61 | edit: edit.finish(), | 61 | edit: edit.finish(), |
62 | cursor_position: Some(offset), | 62 | cursor_position: Some(offset), |
63 | } | 63 | } |
64 | }) | 64 | }); |
65 | |||
66 | // Insert `derive` after doc comments. | ||
67 | fn derive_insertion_offset(nominal: ast::NominalDef) -> Option<TextUnit> { | ||
68 | let non_ws_child = nominal | ||
69 | .syntax() | ||
70 | .children() | ||
71 | .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?; | ||
72 | Some(non_ws_child.range().start()) | ||
73 | } | ||
65 | } | 74 | } |
66 | 75 | ||
67 | pub fn add_impl<'a>( | 76 | pub fn add_impl<'a>( |
@@ -181,7 +190,7 @@ mod tests { | |||
181 | } | 190 | } |
182 | 191 | ||
183 | #[test] | 192 | #[test] |
184 | fn test_add_derive() { | 193 | fn add_derive_new() { |
185 | check_action( | 194 | check_action( |
186 | "struct Foo { a: i32, <|>}", | 195 | "struct Foo { a: i32, <|>}", |
187 | "#[derive(<|>)]\nstruct Foo { a: i32, }", | 196 | "#[derive(<|>)]\nstruct Foo { a: i32, }", |
@@ -192,6 +201,10 @@ mod tests { | |||
192 | "#[derive(<|>)]\nstruct Foo { a: i32, }", | 201 | "#[derive(<|>)]\nstruct Foo { a: i32, }", |
193 | |file, off| add_derive(file, off).map(|f| f()), | 202 | |file, off| add_derive(file, off).map(|f| f()), |
194 | ); | 203 | ); |
204 | } | ||
205 | |||
206 | #[test] | ||
207 | fn add_derive_existing() { | ||
195 | check_action( | 208 | check_action( |
196 | "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", | 209 | "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", |
197 | "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", | 210 | "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", |
@@ -200,6 +213,24 @@ mod tests { | |||
200 | } | 213 | } |
201 | 214 | ||
202 | #[test] | 215 | #[test] |
216 | fn add_derive_new_with_doc_comment() { | ||
217 | check_action( | ||
218 | " | ||
219 | /// `Foo` is a pretty important struct. | ||
220 | /// It does stuff. | ||
221 | struct Foo { a: i32<|>, } | ||
222 | ", | ||
223 | " | ||
224 | /// `Foo` is a pretty important struct. | ||
225 | /// It does stuff. | ||
226 | #[derive(<|>)] | ||
227 | struct Foo { a: i32, } | ||
228 | ", | ||
229 | |file, off| add_derive(file, off).map(|f| f()), | ||
230 | ); | ||
231 | } | ||
232 | |||
233 | #[test] | ||
203 | fn test_add_impl() { | 234 | fn test_add_impl() { |
204 | check_action( | 235 | check_action( |
205 | "struct Foo {<|>}\n", | 236 | "struct Foo {<|>}\n", |