diff options
author | Jonas Schievink <[email protected]> | 2021-04-13 19:32:45 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-04-13 23:03:04 +0100 |
commit | 30aae2cefb9d068055ca8d250d04a288e3684394 (patch) | |
tree | 081a70d030c79437074e2d5ba15f7a9efd5d01cf /crates | |
parent | 10a243ea55565a0dd1de52f8f802c3e3a7bfef54 (diff) |
Move cursor position when using item movers
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide/src/move_item.rs | 100 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 9 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 12 |
4 files changed, 75 insertions, 48 deletions
diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs index 8d37f4f92..246f10a0a 100644 --- a/crates/ide/src/move_item.rs +++ b/crates/ide/src/move_item.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use std::iter::once; | 1 | use std::{iter::once, mem}; |
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::{base_db::FileRange, RootDatabase}; | 4 | use ide_db::{base_db::FileRange, RootDatabase}; |
@@ -102,7 +102,7 @@ fn move_in_direction( | |||
102 | ast::GenericArgList(it) => swap_sibling_in_list(node, it.generic_args(), range, direction), | 102 | ast::GenericArgList(it) => swap_sibling_in_list(node, it.generic_args(), range, direction), |
103 | ast::VariantList(it) => swap_sibling_in_list(node, it.variants(), range, direction), | 103 | ast::VariantList(it) => swap_sibling_in_list(node, it.variants(), range, direction), |
104 | ast::TypeBoundList(it) => swap_sibling_in_list(node, it.bounds(), range, direction), | 104 | ast::TypeBoundList(it) => swap_sibling_in_list(node, it.bounds(), range, direction), |
105 | _ => Some(replace_nodes(node, &match direction { | 105 | _ => Some(replace_nodes(range, node, &match direction { |
106 | Direction::Up => node.prev_sibling(), | 106 | Direction::Up => node.prev_sibling(), |
107 | Direction::Down => node.next_sibling(), | 107 | Direction::Down => node.next_sibling(), |
108 | }?)) | 108 | }?)) |
@@ -125,7 +125,7 @@ fn swap_sibling_in_list<A: AstNode + Clone, I: Iterator<Item = A>>( | |||
125 | .next(); | 125 | .next(); |
126 | 126 | ||
127 | if let Some((l, r)) = list_lookup { | 127 | if let Some((l, r)) = list_lookup { |
128 | Some(replace_nodes(l.syntax(), r.syntax())) | 128 | Some(replace_nodes(range, l.syntax(), r.syntax())) |
129 | } else { | 129 | } else { |
130 | // Cursor is beyond any movable list item (for example, on curly brace in enum). | 130 | // Cursor is beyond any movable list item (for example, on curly brace in enum). |
131 | // It's not necessary, that parent of list is movable (arg list's parent is not, for example), | 131 | // It's not necessary, that parent of list is movable (arg list's parent is not, for example), |
@@ -134,11 +134,38 @@ fn swap_sibling_in_list<A: AstNode + Clone, I: Iterator<Item = A>>( | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | fn replace_nodes(first: &SyntaxNode, second: &SyntaxNode) -> TextEdit { | 137 | fn replace_nodes<'a>( |
138 | range: TextRange, | ||
139 | mut first: &'a SyntaxNode, | ||
140 | mut second: &'a SyntaxNode, | ||
141 | ) -> TextEdit { | ||
142 | let cursor_offset = if range.is_empty() { | ||
143 | // FIXME: `applySnippetTextEdits` does not support non-empty selection ranges | ||
144 | if first.text_range().contains_range(range) { | ||
145 | Some(range.start() - first.text_range().start()) | ||
146 | } else if second.text_range().contains_range(range) { | ||
147 | mem::swap(&mut first, &mut second); | ||
148 | Some(range.start() - first.text_range().start()) | ||
149 | } else { | ||
150 | None | ||
151 | } | ||
152 | } else { | ||
153 | None | ||
154 | }; | ||
155 | |||
156 | let first_with_cursor = match cursor_offset { | ||
157 | Some(offset) => { | ||
158 | let mut item_text = first.text().to_string(); | ||
159 | item_text.insert_str(offset.into(), "$0"); | ||
160 | item_text | ||
161 | } | ||
162 | None => first.text().to_string(), | ||
163 | }; | ||
164 | |||
138 | let mut edit = TextEditBuilder::default(); | 165 | let mut edit = TextEditBuilder::default(); |
139 | 166 | ||
140 | algo::diff(first, second).into_text_edit(&mut edit); | 167 | algo::diff(first, second).into_text_edit(&mut edit); |
141 | algo::diff(second, first).into_text_edit(&mut edit); | 168 | edit.replace(second.text_range(), first_with_cursor); |
142 | 169 | ||
143 | edit.finish() | 170 | edit.finish() |
144 | } | 171 | } |
@@ -188,7 +215,7 @@ fn main() { | |||
188 | expect![[r#" | 215 | expect![[r#" |
189 | fn main() { | 216 | fn main() { |
190 | match true { | 217 | match true { |
191 | false => { | 218 | false =>$0 { |
192 | println!("Test"); | 219 | println!("Test"); |
193 | }, | 220 | }, |
194 | true => { | 221 | true => { |
@@ -222,7 +249,7 @@ fn main() { | |||
222 | false => { | 249 | false => { |
223 | println!("Test"); | 250 | println!("Test"); |
224 | }, | 251 | }, |
225 | true => { | 252 | true =>$0 { |
226 | println!("Hello, world"); | 253 | println!("Hello, world"); |
227 | } | 254 | } |
228 | }; | 255 | }; |
@@ -274,7 +301,7 @@ fn main() { | |||
274 | "#, | 301 | "#, |
275 | expect![[r#" | 302 | expect![[r#" |
276 | fn main() { | 303 | fn main() { |
277 | let test2 = 456; | 304 | let test2$0 = 456; |
278 | let test = 123; | 305 | let test = 123; |
279 | } | 306 | } |
280 | "#]], | 307 | "#]], |
@@ -293,7 +320,7 @@ fn main() { | |||
293 | "#, | 320 | "#, |
294 | expect![[r#" | 321 | expect![[r#" |
295 | fn main() { | 322 | fn main() { |
296 | println!("All I want to say is..."); | 323 | println!("All I want to say is...");$0 |
297 | println!("Hello, world"); | 324 | println!("Hello, world"); |
298 | } | 325 | } |
299 | "#]], | 326 | "#]], |
@@ -313,7 +340,7 @@ fn main() { | |||
313 | fn main() { | 340 | fn main() { |
314 | if true { | 341 | if true { |
315 | println!("Test"); | 342 | println!("Test"); |
316 | } | 343 | }$0 |
317 | 344 | ||
318 | println!("Hello, world"); | 345 | println!("Hello, world"); |
319 | } | 346 | } |
@@ -334,7 +361,7 @@ fn main() { | |||
334 | fn main() { | 361 | fn main() { |
335 | for i in 0..10 { | 362 | for i in 0..10 { |
336 | println!("Test"); | 363 | println!("Test"); |
337 | } | 364 | }$0 |
338 | 365 | ||
339 | println!("Hello, world"); | 366 | println!("Hello, world"); |
340 | } | 367 | } |
@@ -355,7 +382,7 @@ fn main() { | |||
355 | fn main() { | 382 | fn main() { |
356 | loop { | 383 | loop { |
357 | println!("Test"); | 384 | println!("Test"); |
358 | } | 385 | }$0 |
359 | 386 | ||
360 | println!("Hello, world"); | 387 | println!("Hello, world"); |
361 | } | 388 | } |
@@ -376,7 +403,7 @@ fn main() { | |||
376 | fn main() { | 403 | fn main() { |
377 | while true { | 404 | while true { |
378 | println!("Test"); | 405 | println!("Test"); |
379 | } | 406 | }$0 |
380 | 407 | ||
381 | println!("Hello, world"); | 408 | println!("Hello, world"); |
382 | } | 409 | } |
@@ -393,7 +420,7 @@ fn main() { | |||
393 | "#, | 420 | "#, |
394 | expect![[r#" | 421 | expect![[r#" |
395 | fn main() { | 422 | fn main() { |
396 | return 123; | 423 | return 123;$0 |
397 | 424 | ||
398 | println!("Hello, world"); | 425 | println!("Hello, world"); |
399 | } | 426 | } |
@@ -430,7 +457,7 @@ fn main() {} | |||
430 | fn foo() {}$0$0 | 457 | fn foo() {}$0$0 |
431 | "#, | 458 | "#, |
432 | expect![[r#" | 459 | expect![[r#" |
433 | fn foo() {} | 460 | fn foo() {}$0 |
434 | 461 | ||
435 | fn main() {} | 462 | fn main() {} |
436 | "#]], | 463 | "#]], |
@@ -451,7 +478,7 @@ impl Wow for Yay $0$0{} | |||
451 | expect![[r#" | 478 | expect![[r#" |
452 | struct Yay; | 479 | struct Yay; |
453 | 480 | ||
454 | impl Wow for Yay {} | 481 | impl Wow for Yay $0{} |
455 | 482 | ||
456 | trait Wow {} | 483 | trait Wow {} |
457 | "#]], | 484 | "#]], |
@@ -467,7 +494,7 @@ use std::vec::Vec; | |||
467 | use std::collections::HashMap$0$0; | 494 | use std::collections::HashMap$0$0; |
468 | "#, | 495 | "#, |
469 | expect![[r#" | 496 | expect![[r#" |
470 | use std::collections::HashMap; | 497 | use std::collections::HashMap$0; |
471 | use std::vec::Vec; | 498 | use std::vec::Vec; |
472 | "#]], | 499 | "#]], |
473 | Direction::Up, | 500 | Direction::Up, |
@@ -502,7 +529,7 @@ fn main() { | |||
502 | } | 529 | } |
503 | 530 | ||
504 | #[test] | 531 | #[test] |
505 | fn test_moves_param_up() { | 532 | fn test_moves_param() { |
506 | check( | 533 | check( |
507 | r#" | 534 | r#" |
508 | fn test(one: i32, two$0$0: u32) {} | 535 | fn test(one: i32, two$0$0: u32) {} |
@@ -512,7 +539,7 @@ fn main() { | |||
512 | } | 539 | } |
513 | "#, | 540 | "#, |
514 | expect![[r#" | 541 | expect![[r#" |
515 | fn test(two: u32, one: i32) {} | 542 | fn test(two$0: u32, one: i32) {} |
516 | 543 | ||
517 | fn main() { | 544 | fn main() { |
518 | test(123, 456); | 545 | test(123, 456); |
@@ -520,6 +547,15 @@ fn main() { | |||
520 | "#]], | 547 | "#]], |
521 | Direction::Up, | 548 | Direction::Up, |
522 | ); | 549 | ); |
550 | check( | ||
551 | r#" | ||
552 | fn f($0$0arg: u8, arg2: u16) {} | ||
553 | "#, | ||
554 | expect![[r#" | ||
555 | fn f(arg2: u16, $0arg: u8) {} | ||
556 | "#]], | ||
557 | Direction::Down, | ||
558 | ); | ||
523 | } | 559 | } |
524 | 560 | ||
525 | #[test] | 561 | #[test] |
@@ -536,7 +572,7 @@ fn main() { | |||
536 | fn test(one: i32, two: u32) {} | 572 | fn test(one: i32, two: u32) {} |
537 | 573 | ||
538 | fn main() { | 574 | fn main() { |
539 | test(456, 123); | 575 | test(456$0, 123); |
540 | } | 576 | } |
541 | "#]], | 577 | "#]], |
542 | Direction::Up, | 578 | Direction::Up, |
@@ -557,7 +593,7 @@ fn main() { | |||
557 | fn test(one: i32, two: u32) {} | 593 | fn test(one: i32, two: u32) {} |
558 | 594 | ||
559 | fn main() { | 595 | fn main() { |
560 | test(456, 123); | 596 | test(456, 123$0); |
561 | } | 597 | } |
562 | "#]], | 598 | "#]], |
563 | Direction::Down, | 599 | Direction::Down, |
@@ -594,7 +630,7 @@ struct Test<A, B$0$0>(A, B); | |||
594 | fn main() {} | 630 | fn main() {} |
595 | "#, | 631 | "#, |
596 | expect![[r#" | 632 | expect![[r#" |
597 | struct Test<B, A>(A, B); | 633 | struct Test<B$0, A>(A, B); |
598 | 634 | ||
599 | fn main() {} | 635 | fn main() {} |
600 | "#]], | 636 | "#]], |
@@ -616,7 +652,7 @@ fn main() { | |||
616 | struct Test<A, B>(A, B); | 652 | struct Test<A, B>(A, B); |
617 | 653 | ||
618 | fn main() { | 654 | fn main() { |
619 | let t = Test::<&str, i32>(123, "yay"); | 655 | let t = Test::<&str$0, i32>(123, "yay"); |
620 | } | 656 | } |
621 | "#]], | 657 | "#]], |
622 | Direction::Up, | 658 | Direction::Up, |
@@ -636,7 +672,7 @@ fn main() {} | |||
636 | "#, | 672 | "#, |
637 | expect![[r#" | 673 | expect![[r#" |
638 | enum Hello { | 674 | enum Hello { |
639 | Two, | 675 | Two$0, |
640 | One | 676 | One |
641 | } | 677 | } |
642 | 678 | ||
@@ -663,7 +699,7 @@ trait One {} | |||
663 | 699 | ||
664 | trait Two {} | 700 | trait Two {} |
665 | 701 | ||
666 | fn test<T: Two + One>(t: T) {} | 702 | fn test<T: Two$0 + One>(t: T) {} |
667 | 703 | ||
668 | fn main() {} | 704 | fn main() {} |
669 | "#]], | 705 | "#]], |
@@ -709,7 +745,7 @@ trait Yay { | |||
709 | impl Yay for Test { | 745 | impl Yay for Test { |
710 | type One = i32; | 746 | type One = i32; |
711 | 747 | ||
712 | fn inner() { | 748 | fn inner() {$0 |
713 | println!("Mmmm"); | 749 | println!("Mmmm"); |
714 | } | 750 | } |
715 | 751 | ||
@@ -736,7 +772,7 @@ fn test() { | |||
736 | "#, | 772 | "#, |
737 | expect![[r#" | 773 | expect![[r#" |
738 | fn test() { | 774 | fn test() { |
739 | mod hi { | 775 | mod hi {$0 |
740 | fn inner() {} | 776 | fn inner() {} |
741 | } | 777 | } |
742 | 778 | ||
@@ -764,7 +800,7 @@ fn main() {} | |||
764 | expect![[r#" | 800 | expect![[r#" |
765 | fn main() {} | 801 | fn main() {} |
766 | 802 | ||
767 | #[derive(Debug)] | 803 | $0#[derive(Debug)] |
768 | enum FooBar { | 804 | enum FooBar { |
769 | Foo, | 805 | Foo, |
770 | Bar, | 806 | Bar, |
@@ -784,7 +820,7 @@ fn main() {} | |||
784 | expect![[r#" | 820 | expect![[r#" |
785 | fn main() {} | 821 | fn main() {} |
786 | 822 | ||
787 | enum FooBar { | 823 | $0enum FooBar { |
788 | Foo, | 824 | Foo, |
789 | Bar, | 825 | Bar, |
790 | } | 826 | } |
@@ -804,7 +840,7 @@ fn main() {} | |||
804 | expect![[r#" | 840 | expect![[r#" |
805 | struct Test; | 841 | struct Test; |
806 | 842 | ||
807 | impl SomeTrait for Test {} | 843 | $0impl SomeTrait for Test {} |
808 | 844 | ||
809 | trait SomeTrait {} | 845 | trait SomeTrait {} |
810 | 846 | ||
@@ -831,7 +867,7 @@ fn main() {} | |||
831 | enum FooBar { | 867 | enum FooBar { |
832 | Foo, | 868 | Foo, |
833 | Bar, | 869 | Bar, |
834 | } | 870 | }$0 |
835 | "#]], | 871 | "#]], |
836 | Direction::Down, | 872 | Direction::Down, |
837 | ); | 873 | ); |
@@ -848,7 +884,7 @@ fn main() {} | |||
848 | expect![[r#" | 884 | expect![[r#" |
849 | struct Test; | 885 | struct Test; |
850 | 886 | ||
851 | impl SomeTrait for Test {} | 887 | impl SomeTrait for Test {}$0 |
852 | 888 | ||
853 | trait SomeTrait {} | 889 | trait SomeTrait {} |
854 | 890 | ||
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 4f0c9d23c..1f59402e5 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -1410,7 +1410,7 @@ pub(crate) fn handle_open_cargo_toml( | |||
1410 | pub(crate) fn handle_move_item( | 1410 | pub(crate) fn handle_move_item( |
1411 | snap: GlobalStateSnapshot, | 1411 | snap: GlobalStateSnapshot, |
1412 | params: lsp_ext::MoveItemParams, | 1412 | params: lsp_ext::MoveItemParams, |
1413 | ) -> Result<Option<lsp_types::TextDocumentEdit>> { | 1413 | ) -> Result<Vec<lsp_ext::SnippetTextEdit>> { |
1414 | let _p = profile::span("handle_move_item"); | 1414 | let _p = profile::span("handle_move_item"); |
1415 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | 1415 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; |
1416 | let range = from_proto::file_range(&snap, params.text_document, params.range)?; | 1416 | let range = from_proto::file_range(&snap, params.text_document, params.range)?; |
@@ -1421,8 +1421,11 @@ pub(crate) fn handle_move_item( | |||
1421 | }; | 1421 | }; |
1422 | 1422 | ||
1423 | match snap.analysis.move_item(range, direction)? { | 1423 | match snap.analysis.move_item(range, direction)? { |
1424 | Some(text_edit) => Ok(Some(to_proto::text_document_edit(&snap, file_id, text_edit)?)), | 1424 | Some(text_edit) => { |
1425 | None => Ok(None), | 1425 | let line_index = snap.file_line_index(file_id)?; |
1426 | Ok(to_proto::snippet_text_edit_vec(&line_index, true, text_edit)) | ||
1427 | } | ||
1428 | None => Ok(vec![]), | ||
1426 | } | 1429 | } |
1427 | } | 1430 | } |
1428 | 1431 | ||
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 81a6f22f1..d648cda32 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -407,7 +407,7 @@ pub enum MoveItem {} | |||
407 | 407 | ||
408 | impl Request for MoveItem { | 408 | impl Request for MoveItem { |
409 | type Params = MoveItemParams; | 409 | type Params = MoveItemParams; |
410 | type Result = Option<lsp_types::TextDocumentEdit>; | 410 | type Result = Vec<SnippetTextEdit>; |
411 | const METHOD: &'static str = "experimental/moveItem"; | 411 | const METHOD: &'static str = "experimental/moveItem"; |
412 | } | 412 | } |
413 | 413 | ||
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 8d7cb9b74..1a1f65f3b 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -688,18 +688,6 @@ pub(crate) fn goto_definition_response( | |||
688 | } | 688 | } |
689 | } | 689 | } |
690 | 690 | ||
691 | pub(crate) fn text_document_edit( | ||
692 | snap: &GlobalStateSnapshot, | ||
693 | file_id: FileId, | ||
694 | edit: TextEdit, | ||
695 | ) -> Result<lsp_types::TextDocumentEdit> { | ||
696 | let text_document = optional_versioned_text_document_identifier(snap, file_id); | ||
697 | let line_index = snap.file_line_index(file_id)?; | ||
698 | let edits = | ||
699 | edit.into_iter().map(|it| lsp_types::OneOf::Left(text_edit(&line_index, it))).collect(); | ||
700 | Ok(lsp_types::TextDocumentEdit { text_document, edits }) | ||
701 | } | ||
702 | |||
703 | pub(crate) fn snippet_text_document_edit( | 691 | pub(crate) fn snippet_text_document_edit( |
704 | snap: &GlobalStateSnapshot, | 692 | snap: &GlobalStateSnapshot, |
705 | is_snippet: bool, | 693 | is_snippet: bool, |