aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-05-20 00:53:21 +0100
committerAleksey Kladov <[email protected]>2020-05-20 00:53:21 +0100
commita04cababaa144d7a6db7b1dd114494b33d281ab9 (patch)
tree70184acba3f9560bf9a6ed0eae889b9e53a85b6c /crates/ra_assists
parente6fc0bdffb213f6e94c5bb4081e6d175ccbd518f (diff)
Use snippets in add_missing_members
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/assist_context.rs16
-rw-r--r--crates/ra_assists/src/handlers/add_function.rs12
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs62
-rw-r--r--crates/ra_assists/src/tests/generated.rs4
-rw-r--r--crates/ra_assists/src/utils.rs31
5 files changed, 82 insertions, 43 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index 0dcd9df61..005c17776 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -194,20 +194,30 @@ impl AssistBuilder {
194 pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) { 194 pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) {
195 self.edit.insert(offset, text.into()) 195 self.edit.insert(offset, text.into())
196 } 196 }
197 /// Append specified `text` at the given `offset` 197 /// Append specified `snippet` at the given `offset`
198 pub(crate) fn insert_snippet( 198 pub(crate) fn insert_snippet(
199 &mut self, 199 &mut self,
200 _cap: SnippetCap, 200 _cap: SnippetCap,
201 offset: TextSize, 201 offset: TextSize,
202 text: impl Into<String>, 202 snippet: impl Into<String>,
203 ) { 203 ) {
204 self.is_snippet = true; 204 self.is_snippet = true;
205 self.edit.insert(offset, text.into()) 205 self.insert(offset, snippet);
206 } 206 }
207 /// Replaces specified `range` of text with a given string. 207 /// Replaces specified `range` of text with a given string.
208 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { 208 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
209 self.edit.replace(range, replace_with.into()) 209 self.edit.replace(range, replace_with.into())
210 } 210 }
211 /// Replaces specified `range` of text with a given `snippet`.
212 pub(crate) fn replace_snippet(
213 &mut self,
214 _cap: SnippetCap,
215 range: TextRange,
216 snippet: impl Into<String>,
217 ) {
218 self.is_snippet = true;
219 self.replace(range, snippet);
220 }
211 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) { 221 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
212 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit) 222 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
213 } 223 }
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs
index a0709630d..24f931a85 100644
--- a/crates/ra_assists/src/handlers/add_function.rs
+++ b/crates/ra_assists/src/handlers/add_function.rs
@@ -10,7 +10,11 @@ use ra_syntax::{
10}; 10};
11use rustc_hash::{FxHashMap, FxHashSet}; 11use rustc_hash::{FxHashMap, FxHashSet};
12 12
13use crate::{assist_config::SnippetCap, utils::render_snippet, AssistContext, AssistId, Assists}; 13use crate::{
14 assist_config::SnippetCap,
15 utils::{render_snippet, Cursor},
16 AssistContext, AssistId, Assists,
17};
14 18
15// Assist: add_function 19// Assist: add_function
16// 20//
@@ -81,7 +85,11 @@ struct FunctionTemplate {
81impl FunctionTemplate { 85impl FunctionTemplate {
82 fn to_string(&self, cap: Option<SnippetCap>) -> String { 86 fn to_string(&self, cap: Option<SnippetCap>) -> String {
83 let f = match cap { 87 let f = match cap {
84 Some(cap) => render_snippet(cap, self.fn_def.syntax(), self.placeholder_expr.syntax()), 88 Some(cap) => render_snippet(
89 cap,
90 self.fn_def.syntax(),
91 Cursor::Replace(self.placeholder_expr.syntax()),
92 ),
85 None => self.fn_def.to_string(), 93 None => self.fn_def.to_string(),
86 }; 94 };
87 format!("{}{}{}", self.leading_ws, f, self.trailing_ws) 95 format!("{}{}{}", self.leading_ws, f, self.trailing_ws)
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index 22e1156d2..d7aa06947 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11use crate::{ 11use crate::{
12 assist_context::{AssistContext, Assists}, 12 assist_context::{AssistContext, Assists},
13 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, 13 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
14 utils::{get_missing_assoc_items, resolve_target_trait}, 14 utils::{get_missing_assoc_items, render_snippet, resolve_target_trait, Cursor},
15 AssistId, 15 AssistId,
16}; 16};
17 17
@@ -45,7 +45,7 @@ enum AddMissingImplMembersMode {
45// } 45// }
46// 46//
47// impl Trait<u32> for () { 47// impl Trait<u32> for () {
48// fn foo(&self) -> u32 { 48// $0fn foo(&self) -> u32 {
49// todo!() 49// todo!()
50// } 50// }
51// 51//
@@ -89,7 +89,7 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -
89// impl Trait for () { 89// impl Trait for () {
90// Type X = (); 90// Type X = ();
91// fn foo(&self) {} 91// fn foo(&self) {}
92// fn bar(&self) {} 92// $0fn bar(&self) {}
93// 93//
94// } 94// }
95// ``` 95// ```
@@ -147,7 +147,7 @@ fn add_missing_impl_members_inner(
147 } 147 }
148 148
149 let target = impl_def.syntax().text_range(); 149 let target = impl_def.syntax().text_range();
150 acc.add(AssistId(assist_id), label, target, |edit| { 150 acc.add(AssistId(assist_id), label, target, |builder| {
151 let n_existing_items = impl_item_list.assoc_items().count(); 151 let n_existing_items = impl_item_list.assoc_items().count();
152 let source_scope = ctx.sema.scope_for_def(trait_); 152 let source_scope = ctx.sema.scope_for_def(trait_);
153 let target_scope = ctx.sema.scope(impl_item_list.syntax()); 153 let target_scope = ctx.sema.scope(impl_item_list.syntax());
@@ -162,13 +162,21 @@ fn add_missing_impl_members_inner(
162 }) 162 })
163 .map(|it| edit::remove_attrs_and_docs(&it)); 163 .map(|it| edit::remove_attrs_and_docs(&it));
164 let new_impl_item_list = impl_item_list.append_items(items); 164 let new_impl_item_list = impl_item_list.append_items(items);
165 let cursor_position = { 165 let first_new_item = new_impl_item_list.assoc_items().nth(n_existing_items).unwrap();
166 let first_new_item = new_impl_item_list.assoc_items().nth(n_existing_items).unwrap(); 166
167 first_new_item.syntax().text_range().start() 167 let original_range = impl_item_list.syntax().text_range();
168 match ctx.config.snippet_cap {
169 None => builder.replace(original_range, new_impl_item_list.to_string()),
170 Some(cap) => builder.replace_snippet(
171 cap,
172 original_range,
173 render_snippet(
174 cap,
175 new_impl_item_list.syntax(),
176 Cursor::Before(first_new_item.syntax()),
177 ),
178 ),
168 }; 179 };
169
170 edit.replace_ast(impl_item_list, new_impl_item_list);
171 edit.set_cursor(cursor_position);
172 }) 180 })
173} 181}
174 182
@@ -222,7 +230,7 @@ struct S;
222 230
223impl Foo for S { 231impl Foo for S {
224 fn bar(&self) {} 232 fn bar(&self) {}
225 <|>type Output; 233 $0type Output;
226 const CONST: usize = 42; 234 const CONST: usize = 42;
227 fn foo(&self) { 235 fn foo(&self) {
228 todo!() 236 todo!()
@@ -263,7 +271,7 @@ struct S;
263 271
264impl Foo for S { 272impl Foo for S {
265 fn bar(&self) {} 273 fn bar(&self) {}
266 <|>fn foo(&self) { 274 $0fn foo(&self) {
267 todo!() 275 todo!()
268 } 276 }
269 277
@@ -283,7 +291,7 @@ impl Foo for S { <|> }"#,
283trait Foo { fn foo(&self); } 291trait Foo { fn foo(&self); }
284struct S; 292struct S;
285impl Foo for S { 293impl Foo for S {
286 <|>fn foo(&self) { 294 $0fn foo(&self) {
287 todo!() 295 todo!()
288 } 296 }
289}"#, 297}"#,
@@ -302,7 +310,7 @@ impl Foo<u32> for S { <|> }"#,
302trait Foo<T> { fn foo(&self, t: T) -> &T; } 310trait Foo<T> { fn foo(&self, t: T) -> &T; }
303struct S; 311struct S;
304impl Foo<u32> for S { 312impl Foo<u32> for S {
305 <|>fn foo(&self, t: u32) -> &u32 { 313 $0fn foo(&self, t: u32) -> &u32 {
306 todo!() 314 todo!()
307 } 315 }
308}"#, 316}"#,
@@ -321,7 +329,7 @@ impl<U> Foo<U> for S { <|> }"#,
321trait Foo<T> { fn foo(&self, t: T) -> &T; } 329trait Foo<T> { fn foo(&self, t: T) -> &T; }
322struct S; 330struct S;
323impl<U> Foo<U> for S { 331impl<U> Foo<U> for S {
324 <|>fn foo(&self, t: U) -> &U { 332 $0fn foo(&self, t: U) -> &U {
325 todo!() 333 todo!()
326 } 334 }
327}"#, 335}"#,
@@ -340,7 +348,7 @@ impl Foo for S {}<|>"#,
340trait Foo { fn foo(&self); } 348trait Foo { fn foo(&self); }
341struct S; 349struct S;
342impl Foo for S { 350impl Foo for S {
343 <|>fn foo(&self) { 351 $0fn foo(&self) {
344 todo!() 352 todo!()
345 } 353 }
346}"#, 354}"#,
@@ -365,7 +373,7 @@ mod foo {
365} 373}
366struct S; 374struct S;
367impl foo::Foo for S { 375impl foo::Foo for S {
368 <|>fn foo(&self, bar: foo::Bar) { 376 $0fn foo(&self, bar: foo::Bar) {
369 todo!() 377 todo!()
370 } 378 }
371}"#, 379}"#,
@@ -390,7 +398,7 @@ mod foo {
390} 398}
391struct S; 399struct S;
392impl foo::Foo for S { 400impl foo::Foo for S {
393 <|>fn foo(&self, bar: foo::Bar<u32>) { 401 $0fn foo(&self, bar: foo::Bar<u32>) {
394 todo!() 402 todo!()
395 } 403 }
396}"#, 404}"#,
@@ -415,7 +423,7 @@ mod foo {
415} 423}
416struct S; 424struct S;
417impl foo::Foo<u32> for S { 425impl foo::Foo<u32> for S {
418 <|>fn foo(&self, bar: foo::Bar<u32>) { 426 $0fn foo(&self, bar: foo::Bar<u32>) {
419 todo!() 427 todo!()
420 } 428 }
421}"#, 429}"#,
@@ -443,7 +451,7 @@ mod foo {
443struct Param; 451struct Param;
444struct S; 452struct S;
445impl foo::Foo<Param> for S { 453impl foo::Foo<Param> for S {
446 <|>fn foo(&self, bar: Param) { 454 $0fn foo(&self, bar: Param) {
447 todo!() 455 todo!()
448 } 456 }
449}"#, 457}"#,
@@ -470,7 +478,7 @@ mod foo {
470} 478}
471struct S; 479struct S;
472impl foo::Foo for S { 480impl foo::Foo for S {
473 <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { 481 $0fn foo(&self, bar: foo::Bar<u32>::Assoc) {
474 todo!() 482 todo!()
475 } 483 }
476}"#, 484}"#,
@@ -497,7 +505,7 @@ mod foo {
497} 505}
498struct S; 506struct S;
499impl foo::Foo for S { 507impl foo::Foo for S {
500 <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { 508 $0fn foo(&self, bar: foo::Bar<foo::Baz>) {
501 todo!() 509 todo!()
502 } 510 }
503}"#, 511}"#,
@@ -522,7 +530,7 @@ mod foo {
522} 530}
523struct S; 531struct S;
524impl foo::Foo for S { 532impl foo::Foo for S {
525 <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { 533 $0fn foo(&self, bar: dyn Fn(u32) -> i32) {
526 todo!() 534 todo!()
527 } 535 }
528}"#, 536}"#,
@@ -580,7 +588,7 @@ trait Foo {
580} 588}
581struct S; 589struct S;
582impl Foo for S { 590impl Foo for S {
583 <|>type Output; 591 $0type Output;
584 fn foo(&self) { 592 fn foo(&self) {
585 todo!() 593 todo!()
586 } 594 }
@@ -614,7 +622,7 @@ trait Foo {
614} 622}
615struct S; 623struct S;
616impl Foo for S { 624impl Foo for S {
617 <|>fn valid(some: u32) -> bool { false } 625 $0fn valid(some: u32) -> bool { false }
618}"#, 626}"#,
619 ) 627 )
620 } 628 }
@@ -637,7 +645,7 @@ trait Foo<T = Self> {
637 645
638struct S; 646struct S;
639impl Foo for S { 647impl Foo for S {
640 <|>fn bar(&self, other: &Self) { 648 $0fn bar(&self, other: &Self) {
641 todo!() 649 todo!()
642 } 650 }
643}"#, 651}"#,
@@ -662,7 +670,7 @@ trait Foo<T1, T2 = Self> {
662 670
663struct S<T>; 671struct S<T>;
664impl Foo<T> for S<T> { 672impl Foo<T> for S<T> {
665 <|>fn bar(&self, this: &T, that: &Self) { 673 $0fn bar(&self, this: &T, that: &Self) {
666 todo!() 674 todo!()
667 } 675 }
668}"#, 676}"#,
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs
index 1d82c245d..2522ec5df 100644
--- a/crates/ra_assists/src/tests/generated.rs
+++ b/crates/ra_assists/src/tests/generated.rs
@@ -150,7 +150,7 @@ trait Trait {
150impl Trait for () { 150impl Trait for () {
151 Type X = (); 151 Type X = ();
152 fn foo(&self) {} 152 fn foo(&self) {}
153 fn bar(&self) {} 153 $0fn bar(&self) {}
154 154
155} 155}
156"#####, 156"#####,
@@ -180,7 +180,7 @@ trait Trait<T> {
180} 180}
181 181
182impl Trait<u32> for () { 182impl Trait<u32> for () {
183 fn foo(&self) -> u32 { 183 $0fn foo(&self) -> u32 {
184 todo!() 184 todo!()
185 } 185 }
186 186
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 8a26a6808..9af27180b 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -15,18 +15,31 @@ use crate::assist_config::SnippetCap;
15 15
16pub(crate) use insert_use::insert_use_statement; 16pub(crate) use insert_use::insert_use_statement;
17 17
18pub(crate) fn render_snippet( 18#[derive(Clone, Copy, Debug)]
19 _cap: SnippetCap, 19pub(crate) enum Cursor<'a> {
20 node: &SyntaxNode, 20 Replace(&'a SyntaxNode),
21 placeholder: &SyntaxNode, 21 Before(&'a SyntaxNode),
22) -> String { 22}
23 assert!(placeholder.ancestors().any(|it| it == *node)); 23
24 let range = placeholder.text_range() - node.text_range().start(); 24impl<'a> Cursor<'a> {
25 fn node(self) -> &'a SyntaxNode {
26 match self {
27 Cursor::Replace(node) | Cursor::Before(node) => node,
28 }
29 }
30}
31
32pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor) -> String {
33 assert!(cursor.node().ancestors().any(|it| it == *node));
34 let range = cursor.node().text_range() - node.text_range().start();
25 let range: ops::Range<usize> = range.into(); 35 let range: ops::Range<usize> = range.into();
26 36
27 let mut placeholder = placeholder.to_string(); 37 let mut placeholder = cursor.node().to_string();
28 escape(&mut placeholder); 38 escape(&mut placeholder);
29 let tab_stop = format!("${{0:{}}}", placeholder); 39 let tab_stop = match cursor {
40 Cursor::Replace(placeholder) => format!("${{0:{}}}", placeholder),
41 Cursor::Before(placeholder) => format!("$0{}", placeholder),
42 };
30 43
31 let mut buf = node.to_string(); 44 let mut buf = node.to_string();
32 buf.replace_range(range, &tab_stop); 45 buf.replace_range(range, &tab_stop);