diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/assist_context.rs | 16 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/add_function.rs | 12 | ||||
-rw-r--r-- | crates/ra_assists/src/handlers/add_missing_impl_members.rs | 62 | ||||
-rw-r--r-- | crates/ra_assists/src/tests/generated.rs | 4 | ||||
-rw-r--r-- | crates/ra_assists/src/utils.rs | 31 |
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 | }; |
11 | use rustc_hash::{FxHashMap, FxHashSet}; | 11 | use rustc_hash::{FxHashMap, FxHashSet}; |
12 | 12 | ||
13 | use crate::{assist_config::SnippetCap, utils::render_snippet, AssistContext, AssistId, Assists}; | 13 | use 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 { | |||
81 | impl FunctionTemplate { | 85 | impl 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::{ | |||
11 | use crate::{ | 11 | use 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 | ||
223 | impl Foo for S { | 231 | impl 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 | ||
264 | impl Foo for S { | 272 | impl 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 { <|> }"#, | |||
283 | trait Foo { fn foo(&self); } | 291 | trait Foo { fn foo(&self); } |
284 | struct S; | 292 | struct S; |
285 | impl Foo for S { | 293 | impl 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 { <|> }"#, | |||
302 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 310 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
303 | struct S; | 311 | struct S; |
304 | impl Foo<u32> for S { | 312 | impl 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 { <|> }"#, | |||
321 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 329 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
322 | struct S; | 330 | struct S; |
323 | impl<U> Foo<U> for S { | 331 | impl<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 {}<|>"#, | |||
340 | trait Foo { fn foo(&self); } | 348 | trait Foo { fn foo(&self); } |
341 | struct S; | 349 | struct S; |
342 | impl Foo for S { | 350 | impl 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 | } |
366 | struct S; | 374 | struct S; |
367 | impl foo::Foo for S { | 375 | impl 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 | } |
391 | struct S; | 399 | struct S; |
392 | impl foo::Foo for S { | 400 | impl 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 | } |
416 | struct S; | 424 | struct S; |
417 | impl foo::Foo<u32> for S { | 425 | impl 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 { | |||
443 | struct Param; | 451 | struct Param; |
444 | struct S; | 452 | struct S; |
445 | impl foo::Foo<Param> for S { | 453 | impl 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 | } |
471 | struct S; | 479 | struct S; |
472 | impl foo::Foo for S { | 480 | impl 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 | } |
498 | struct S; | 506 | struct S; |
499 | impl foo::Foo for S { | 507 | impl 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 | } |
523 | struct S; | 531 | struct S; |
524 | impl foo::Foo for S { | 532 | impl 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 | } |
581 | struct S; | 589 | struct S; |
582 | impl Foo for S { | 590 | impl 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 | } |
615 | struct S; | 623 | struct S; |
616 | impl Foo for S { | 624 | impl 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 | ||
638 | struct S; | 646 | struct S; |
639 | impl Foo for S { | 647 | impl 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 | ||
663 | struct S<T>; | 671 | struct S<T>; |
664 | impl Foo<T> for S<T> { | 672 | impl 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 { | |||
150 | impl Trait for () { | 150 | impl 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 | ||
182 | impl Trait<u32> for () { | 182 | impl 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 | ||
16 | pub(crate) use insert_use::insert_use_statement; | 16 | pub(crate) use insert_use::insert_use_statement; |
17 | 17 | ||
18 | pub(crate) fn render_snippet( | 18 | #[derive(Clone, Copy, Debug)] |
19 | _cap: SnippetCap, | 19 | pub(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(); | 24 | impl<'a> Cursor<'a> { |
25 | fn node(self) -> &'a SyntaxNode { | ||
26 | match self { | ||
27 | Cursor::Replace(node) | Cursor::Before(node) => node, | ||
28 | } | ||
29 | } | ||
30 | } | ||
31 | |||
32 | pub(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); |