diff options
-rw-r--r-- | crates/ra_assists/src/handlers/add_custom_impl.rs | 51 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/add_derive.rs | 28 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/add_impl.rs | 34 | ||||
-rw-r--r-- | crates/ra_assists/src/tests/generated.rs | 10 | ||||
-rw-r--r-- | docs/user/assists.md | 10 |
5 files changed, 72 insertions, 61 deletions
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs index 2baeb8607..fa70c8496 100644 --- a/crates/ra_assists/src/handlers/add_custom_impl.rs +++ b/crates/ra_assists/src/handlers/add_custom_impl.rs | |||
@@ -25,7 +25,7 @@ use crate::{ | |||
25 | // struct S; | 25 | // struct S; |
26 | // | 26 | // |
27 | // impl Debug for S { | 27 | // impl Debug for S { |
28 | // | 28 | // $0 |
29 | // } | 29 | // } |
30 | // ``` | 30 | // ``` |
31 | pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 31 | pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
@@ -52,7 +52,7 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
52 | 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); |
53 | 53 | ||
54 | let target = attr.syntax().text_range(); | 54 | let target = attr.syntax().text_range(); |
55 | acc.add(AssistId("add_custom_impl"), label, target, |edit| { | 55 | acc.add(AssistId("add_custom_impl"), label, target, |builder| { |
56 | let new_attr_input = input | 56 | let new_attr_input = input |
57 | .syntax() | 57 | .syntax() |
58 | .descendants_with_tokens() | 58 | .descendants_with_tokens() |
@@ -63,20 +63,11 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
63 | let has_more_derives = !new_attr_input.is_empty(); | 63 | let has_more_derives = !new_attr_input.is_empty(); |
64 | 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(); |
65 | 65 | ||
66 | let mut buf = String::new(); | 66 | if has_more_derives { |
67 | buf.push_str("\n\nimpl "); | 67 | builder.replace(input.syntax().text_range(), new_attr_input); |
68 | buf.push_str(trait_token.text().as_str()); | ||
69 | buf.push_str(" for "); | ||
70 | buf.push_str(annotated_name.as_str()); | ||
71 | buf.push_str(" {\n"); | ||
72 | |||
73 | let cursor_delta = if has_more_derives { | ||
74 | let delta = input.syntax().text_range().len() - TextSize::of(&new_attr_input); | ||
75 | edit.replace(input.syntax().text_range(), new_attr_input); | ||
76 | delta | ||
77 | } else { | 68 | } else { |
78 | let attr_range = attr.syntax().text_range(); | 69 | let attr_range = attr.syntax().text_range(); |
79 | edit.delete(attr_range); | 70 | builder.delete(attr_range); |
80 | 71 | ||
81 | let line_break_range = attr | 72 | let line_break_range = attr |
82 | .syntax() | 73 | .syntax() |
@@ -84,14 +75,24 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
84 | .filter(|t| t.kind() == WHITESPACE) | 75 | .filter(|t| t.kind() == WHITESPACE) |
85 | .map(|t| t.text_range()) | 76 | .map(|t| t.text_range()) |
86 | .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0))); | 77 | .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0))); |
87 | edit.delete(line_break_range); | 78 | builder.delete(line_break_range); |
88 | 79 | } | |
89 | attr_range.len() + line_break_range.len() | 80 | |
90 | }; | 81 | match ctx.config.snippet_cap { |
91 | 82 | Some(cap) => { | |
92 | edit.set_cursor(start_offset + TextSize::of(&buf) - cursor_delta); | 83 | builder.insert_snippet( |
93 | buf.push_str("\n}"); | 84 | cap, |
94 | 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 | } | ||
95 | }) | 96 | }) |
96 | } | 97 | } |
97 | 98 | ||
@@ -117,7 +118,7 @@ struct Foo { | |||
117 | } | 118 | } |
118 | 119 | ||
119 | impl Debug for Foo { | 120 | impl Debug for Foo { |
120 | <|> | 121 | $0 |
121 | } | 122 | } |
122 | ", | 123 | ", |
123 | ) | 124 | ) |
@@ -139,7 +140,7 @@ pub struct Foo { | |||
139 | } | 140 | } |
140 | 141 | ||
141 | impl Debug for Foo { | 142 | impl Debug for Foo { |
142 | <|> | 143 | $0 |
143 | } | 144 | } |
144 | ", | 145 | ", |
145 | ) | 146 | ) |
@@ -158,7 +159,7 @@ struct Foo {} | |||
158 | struct Foo {} | 159 | struct Foo {} |
159 | 160 | ||
160 | impl Debug for Foo { | 161 | impl Debug for Foo { |
161 | <|> | 162 | $0 |
162 | } | 163 | } |
163 | ", | 164 | ", |
164 | ) | 165 | ) |
diff --git a/crates/ra_assists/src/handlers/add_derive.rs b/crates/ra_assists/src/handlers/add_derive.rs index fb08c19e9..b123b8498 100644 --- a/crates/ra_assists/src/handlers/add_derive.rs +++ b/crates/ra_assists/src/handlers/add_derive.rs | |||
@@ -18,31 +18,37 @@ use crate::{AssistContext, AssistId, Assists}; | |||
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 | // ``` |
27 | pub(crate) fn add_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 27 | pub(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 | let target = nominal.syntax().text_range(); | 31 | let target = nominal.syntax().text_range(); |
31 | acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |edit| { | 32 | acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |builder| { |
32 | let derive_attr = nominal | 33 | let derive_attr = nominal |
33 | .attrs() | 34 | .attrs() |
34 | .filter_map(|x| x.as_simple_call()) | 35 | .filter_map(|x| x.as_simple_call()) |
35 | .filter(|(name, _arg)| name == "derive") | 36 | .filter(|(name, _arg)| name == "derive") |
36 | .map(|(_name, arg)| arg) | 37 | .map(|(_name, arg)| arg) |
37 | .next(); | 38 | .next(); |
38 | let offset = match derive_attr { | 39 | match derive_attr { |
39 | None => { | 40 | None => { |
40 | edit.insert(node_start, "#[derive()]\n"); | 41 | builder.insert_snippet(cap, node_start, "#[derive($0)]\n"); |
41 | 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 | ) | ||
42 | } | 50 | } |
43 | Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'), | ||
44 | }; | 51 | }; |
45 | edit.set_cursor(offset) | ||
46 | }) | 52 | }) |
47 | } | 53 | } |
48 | 54 | ||
@@ -66,12 +72,12 @@ mod tests { | |||
66 | check_assist( | 72 | check_assist( |
67 | add_derive, | 73 | add_derive, |
68 | "struct Foo { a: i32, <|>}", | 74 | "struct Foo { a: i32, <|>}", |
69 | "#[derive(<|>)]\nstruct Foo { a: i32, }", | 75 | "#[derive($0)]\nstruct Foo { a: i32, }", |
70 | ); | 76 | ); |
71 | check_assist( | 77 | check_assist( |
72 | add_derive, | 78 | add_derive, |
73 | "struct Foo { <|> a: i32, }", | 79 | "struct Foo { <|> a: i32, }", |
74 | "#[derive(<|>)]\nstruct Foo { a: i32, }", | 80 | "#[derive($0)]\nstruct Foo { a: i32, }", |
75 | ); | 81 | ); |
76 | } | 82 | } |
77 | 83 | ||
@@ -80,7 +86,7 @@ mod tests { | |||
80 | check_assist( | 86 | check_assist( |
81 | add_derive, | 87 | add_derive, |
82 | "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", | 88 | "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", |
83 | "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", | 89 | "#[derive(Clone$0)]\nstruct Foo { a: i32, }", |
84 | ); | 90 | ); |
85 | } | 91 | } |
86 | 92 | ||
@@ -96,7 +102,7 @@ struct Foo { a: i32<|>, } | |||
96 | " | 102 | " |
97 | /// `Foo` is a pretty important struct. | 103 | /// `Foo` is a pretty important struct. |
98 | /// It does stuff. | 104 | /// It does stuff. |
99 | #[derive(<|>)] | 105 | #[derive($0)] |
100 | struct Foo { a: i32, } | 106 | struct Foo { a: i32, } |
101 | ", | 107 | ", |
102 | ); | 108 | ); |
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index df114a0d8..eceba7d0a 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs | |||
@@ -1,7 +1,4 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; |
2 | ast::{self, AstNode, NameOwner, TypeParamsOwner}, | ||
3 | TextSize, | ||
4 | }; | ||
5 | use stdx::{format_to, SepBy}; | 2 | use stdx::{format_to, SepBy}; |
6 | 3 | ||
7 | use crate::{AssistContext, AssistId, Assists}; | 4 | use crate::{AssistContext, AssistId, Assists}; |
@@ -12,17 +9,17 @@ use crate::{AssistContext, AssistId, Assists}; | |||
12 | // | 9 | // |
13 | // ``` | 10 | // ``` |
14 | // struct Ctx<T: Clone> { | 11 | // struct Ctx<T: Clone> { |
15 | // data: T,<|> | 12 | // data: T,<|> |
16 | // } | 13 | // } |
17 | // ``` | 14 | // ``` |
18 | // -> | 15 | // -> |
19 | // ``` | 16 | // ``` |
20 | // struct Ctx<T: Clone> { | 17 | // struct Ctx<T: Clone> { |
21 | // data: T, | 18 | // data: T, |
22 | // } | 19 | // } |
23 | // | 20 | // |
24 | // impl<T: Clone> Ctx<T> { | 21 | // impl<T: Clone> Ctx<T> { |
25 | // | 22 | // $0 |
26 | // } | 23 | // } |
27 | // ``` | 24 | // ``` |
28 | pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 25 | pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
@@ -50,30 +47,37 @@ pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
50 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); | 47 | let generic_params = lifetime_params.chain(type_params).sep_by(", "); |
51 | format_to!(buf, "<{}>", generic_params) | 48 | format_to!(buf, "<{}>", generic_params) |
52 | } | 49 | } |
53 | buf.push_str(" {\n"); | 50 | match ctx.config.snippet_cap { |
54 | edit.set_cursor(start_offset + TextSize::of(&buf)); | 51 | Some(cap) => { |
55 | buf.push_str("\n}"); | 52 | buf.push_str(" {\n $0\n}"); |
56 | edit.insert(start_offset, buf); | 53 | edit.insert_snippet(cap, start_offset, buf); |
54 | } | ||
55 | None => { | ||
56 | buf.push_str(" {\n}"); | ||
57 | edit.insert(start_offset, buf); | ||
58 | } | ||
59 | } | ||
57 | }) | 60 | }) |
58 | } | 61 | } |
59 | 62 | ||
60 | #[cfg(test)] | 63 | #[cfg(test)] |
61 | mod tests { | 64 | mod tests { |
62 | use super::*; | ||
63 | use crate::tests::{check_assist, check_assist_target}; | 65 | use crate::tests::{check_assist, check_assist_target}; |
64 | 66 | ||
67 | use super::*; | ||
68 | |||
65 | #[test] | 69 | #[test] |
66 | fn test_add_impl() { | 70 | fn test_add_impl() { |
67 | check_assist(add_impl, "struct Foo {<|>}\n", "struct Foo {}\n\nimpl Foo {\n<|>\n}\n"); | 71 | check_assist(add_impl, "struct Foo {<|>}\n", "struct Foo {}\n\nimpl Foo {\n $0\n}\n"); |
68 | check_assist( | 72 | check_assist( |
69 | add_impl, | 73 | add_impl, |
70 | "struct Foo<T: Clone> {<|>}", | 74 | "struct Foo<T: Clone> {<|>}", |
71 | "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n<|>\n}", | 75 | "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n $0\n}", |
72 | ); | 76 | ); |
73 | check_assist( | 77 | check_assist( |
74 | add_impl, | 78 | add_impl, |
75 | "struct Foo<'a, T: Foo<'a>> {<|>}", | 79 | "struct Foo<'a, T: Foo<'a>> {<|>}", |
76 | "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n<|>\n}", | 80 | "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n $0\n}", |
77 | ); | 81 | ); |
78 | } | 82 | } |
79 | 83 | ||
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs index 972dbd251..9487c9239 100644 --- a/crates/ra_assists/src/tests/generated.rs +++ b/crates/ra_assists/src/tests/generated.rs | |||
@@ -15,7 +15,7 @@ struct S; | |||
15 | struct S; | 15 | struct S; |
16 | 16 | ||
17 | impl Debug for S { | 17 | impl Debug for S { |
18 | 18 | $0 | |
19 | } | 19 | } |
20 | "#####, | 20 | "#####, |
21 | ) | 21 | ) |
@@ -32,7 +32,7 @@ struct Point { | |||
32 | } | 32 | } |
33 | "#####, | 33 | "#####, |
34 | r#####" | 34 | r#####" |
35 | #[derive()] | 35 | #[derive($0)] |
36 | struct Point { | 36 | struct Point { |
37 | x: u32, | 37 | x: u32, |
38 | y: u32, | 38 | y: u32, |
@@ -108,16 +108,16 @@ fn doctest_add_impl() { | |||
108 | "add_impl", | 108 | "add_impl", |
109 | r#####" | 109 | r#####" |
110 | struct Ctx<T: Clone> { | 110 | struct Ctx<T: Clone> { |
111 | data: T,<|> | 111 | data: T,<|> |
112 | } | 112 | } |
113 | "#####, | 113 | "#####, |
114 | r#####" | 114 | r#####" |
115 | struct Ctx<T: Clone> { | 115 | struct Ctx<T: Clone> { |
116 | data: T, | 116 | data: T, |
117 | } | 117 | } |
118 | 118 | ||
119 | impl<T: Clone> Ctx<T> { | 119 | impl<T: Clone> Ctx<T> { |
120 | 120 | $0 | |
121 | } | 121 | } |
122 | "#####, | 122 | "#####, |
123 | ) | 123 | ) |
diff --git a/docs/user/assists.md b/docs/user/assists.md index 692fd4f52..41c5df528 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md | |||
@@ -17,7 +17,7 @@ struct S; | |||
17 | struct S; | 17 | struct S; |
18 | 18 | ||
19 | impl Debug for S { | 19 | impl Debug for S { |
20 | 20 | $0 | |
21 | } | 21 | } |
22 | ``` | 22 | ``` |
23 | 23 | ||
@@ -33,7 +33,7 @@ struct Point { | |||
33 | } | 33 | } |
34 | 34 | ||
35 | // AFTER | 35 | // AFTER |
36 | #[derive()] | 36 | #[derive($0)] |
37 | struct Point { | 37 | struct Point { |
38 | x: u32, | 38 | x: u32, |
39 | y: u32, | 39 | y: u32, |
@@ -105,16 +105,16 @@ Adds a new inherent impl for a type. | |||
105 | ```rust | 105 | ```rust |
106 | // BEFORE | 106 | // BEFORE |
107 | struct Ctx<T: Clone> { | 107 | struct Ctx<T: Clone> { |
108 | data: T,┃ | 108 | data: T,┃ |
109 | } | 109 | } |
110 | 110 | ||
111 | // AFTER | 111 | // AFTER |
112 | struct Ctx<T: Clone> { | 112 | struct Ctx<T: Clone> { |
113 | data: T, | 113 | data: T, |
114 | } | 114 | } |
115 | 115 | ||
116 | impl<T: Clone> Ctx<T> { | 116 | impl<T: Clone> Ctx<T> { |
117 | 117 | $0 | |
118 | } | 118 | } |
119 | ``` | 119 | ``` |
120 | 120 | ||