diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide/src/join_lines.rs | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index 2c077ed1f..7fcae13e0 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs | |||
@@ -7,6 +7,7 @@ use syntax::{ | |||
7 | SyntaxKind::{self, USE_TREE, WHITESPACE}, | 7 | SyntaxKind::{self, USE_TREE, WHITESPACE}, |
8 | SyntaxNode, SyntaxToken, TextRange, TextSize, T, | 8 | SyntaxNode, SyntaxToken, TextRange, TextSize, T, |
9 | }; | 9 | }; |
10 | use test_utils::mark; | ||
10 | use text_edit::{TextEdit, TextEditBuilder}; | 11 | use text_edit::{TextEdit, TextEditBuilder}; |
11 | 12 | ||
12 | // Feature: Join Lines | 13 | // Feature: Join Lines |
@@ -44,9 +45,9 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit { | |||
44 | let text = token.text(); | 45 | let text = token.text(); |
45 | for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { | 46 | for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { |
46 | let pos: TextSize = (pos as u32).into(); | 47 | let pos: TextSize = (pos as u32).into(); |
47 | let off = token.text_range().start() + range.start() + pos; | 48 | let offset = token.text_range().start() + range.start() + pos; |
48 | if !edit.invalidates_offset(off) { | 49 | if !edit.invalidates_offset(offset) { |
49 | remove_newline(&mut edit, &token, off); | 50 | remove_newline(&mut edit, &token, offset); |
50 | } | 51 | } |
51 | } | 52 | } |
52 | } | 53 | } |
@@ -56,14 +57,25 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit { | |||
56 | 57 | ||
57 | fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextSize) { | 58 | fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextSize) { |
58 | if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { | 59 | if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { |
59 | // The node is either the first or the last in the file | 60 | let mut string_open_quote = false; |
60 | let suff = &token.text()[TextRange::new( | 61 | if let Some(string) = ast::String::cast(token.clone()) { |
61 | offset - token.text_range().start() + TextSize::of('\n'), | 62 | if let Some(range) = string.open_quote_text_range() { |
62 | TextSize::of(token.text()), | 63 | mark::hit!(join_string_literal); |
63 | )]; | 64 | string_open_quote = range.end() == offset; |
64 | let spaces = suff.bytes().take_while(|&b| b == b' ').count(); | 65 | } |
65 | 66 | } | |
66 | edit.replace(TextRange::at(offset, ((spaces + 1) as u32).into()), " ".to_string()); | 67 | |
68 | let n_spaces_after_line_break = { | ||
69 | let suff = &token.text()[TextRange::new( | ||
70 | offset - token.text_range().start() + TextSize::of('\n'), | ||
71 | TextSize::of(token.text()), | ||
72 | )]; | ||
73 | suff.bytes().take_while(|&b| b == b' ').count() | ||
74 | }; | ||
75 | |||
76 | let range = TextRange::at(offset, ((n_spaces_after_line_break + 1) as u32).into()); | ||
77 | let replace_with = if string_open_quote { "" } else { " " }; | ||
78 | edit.replace(range, replace_with.to_string()); | ||
67 | return; | 79 | return; |
68 | } | 80 | } |
69 | 81 | ||
@@ -194,7 +206,7 @@ fn compute_ws(left: SyntaxKind, right: SyntaxKind) -> &'static str { | |||
194 | #[cfg(test)] | 206 | #[cfg(test)] |
195 | mod tests { | 207 | mod tests { |
196 | use syntax::SourceFile; | 208 | use syntax::SourceFile; |
197 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range}; | 209 | use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range, mark}; |
198 | 210 | ||
199 | use super::*; | 211 | use super::*; |
200 | 212 | ||
@@ -771,4 +783,42 @@ fn foo() { | |||
771 | ", | 783 | ", |
772 | ); | 784 | ); |
773 | } | 785 | } |
786 | |||
787 | #[test] | ||
788 | fn join_string_literal() { | ||
789 | mark::check!(join_string_literal); | ||
790 | check_join_lines( | ||
791 | r#" | ||
792 | fn main() { | ||
793 | $0" | ||
794 | hello | ||
795 | "; | ||
796 | } | ||
797 | "#, | ||
798 | r#" | ||
799 | fn main() { | ||
800 | $0"hello | ||
801 | "; | ||
802 | } | ||
803 | "#, | ||
804 | ); | ||
805 | |||
806 | check_join_lines( | ||
807 | r#" | ||
808 | fn main() { | ||
809 | " | ||
810 | $0hello | ||
811 | world | ||
812 | "; | ||
813 | } | ||
814 | "#, | ||
815 | r#" | ||
816 | fn main() { | ||
817 | " | ||
818 | $0hello world | ||
819 | "; | ||
820 | } | ||
821 | "#, | ||
822 | ); | ||
823 | } | ||
774 | } | 824 | } |