diff options
Diffstat (limited to 'crates/ra_editor/src/extend_selection.rs')
-rw-r--r-- | crates/ra_editor/src/extend_selection.rs | 58 |
1 files changed, 24 insertions, 34 deletions
diff --git a/crates/ra_editor/src/extend_selection.rs b/crates/ra_editor/src/extend_selection.rs index ab03a717e..9ee1df281 100644 --- a/crates/ra_editor/src/extend_selection.rs +++ b/crates/ra_editor/src/extend_selection.rs | |||
@@ -1,7 +1,8 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | File, TextRange, SyntaxNodeRef, TextUnit, Direction, | 2 | algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, |
3 | Direction, File, | ||
3 | SyntaxKind::*, | 4 | SyntaxKind::*, |
4 | algo::{find_leaf_at_offset, LeafAtOffset, find_covering_node}, | 5 | SyntaxNodeRef, TextRange, TextUnit, |
5 | }; | 6 | }; |
6 | 7 | ||
7 | pub fn extend_selection(file: &File, range: TextRange) -> Option<TextRange> { | 8 | pub fn extend_selection(file: &File, range: TextRange) -> Option<TextRange> { |
@@ -20,11 +21,11 @@ pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option<TextRange> | |||
20 | LeafAtOffset::None => return None, | 21 | LeafAtOffset::None => return None, |
21 | LeafAtOffset::Single(l) => { | 22 | LeafAtOffset::Single(l) => { |
22 | if l.kind() == COMMENT { | 23 | if l.kind() == COMMENT { |
23 | extend_single_word_in_comment(l, offset).unwrap_or_else(||l.range()) | 24 | extend_single_word_in_comment(l, offset).unwrap_or_else(|| l.range()) |
24 | } else { | 25 | } else { |
25 | l.range() | 26 | l.range() |
26 | } | 27 | } |
27 | }, | 28 | } |
28 | LeafAtOffset::Between(l, r) => pick_best(l, r).range(), | 29 | LeafAtOffset::Between(l, r) => pick_best(l, r).range(), |
29 | }; | 30 | }; |
30 | return Some(leaf_range); | 31 | return Some(leaf_range); |
@@ -66,7 +67,7 @@ fn extend_ws(root: SyntaxNodeRef, ws: SyntaxNodeRef, offset: TextUnit) -> TextRa | |||
66 | if let Some(node) = ws.next_sibling() { | 67 | if let Some(node) = ws.next_sibling() { |
67 | let start = match ws_prefix.rfind('\n') { | 68 | let start = match ws_prefix.rfind('\n') { |
68 | Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32), | 69 | Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32), |
69 | None => node.range().start() | 70 | None => node.range().start(), |
70 | }; | 71 | }; |
71 | let end = if root.text().char_at(node.range().end()) == Some('\n') { | 72 | let end = if root.text().char_at(node.range().end()) == Some('\n') { |
72 | node.range().end() + TextUnit::of_char('\n') | 73 | node.range().end() + TextUnit::of_char('\n') |
@@ -94,10 +95,7 @@ fn extend_comments(node: SyntaxNodeRef) -> Option<TextRange> { | |||
94 | let prev = adj_comments(node, Direction::Prev); | 95 | let prev = adj_comments(node, Direction::Prev); |
95 | let next = adj_comments(node, Direction::Next); | 96 | let next = adj_comments(node, Direction::Next); |
96 | if prev != next { | 97 | if prev != next { |
97 | Some(TextRange::from_to( | 98 | Some(TextRange::from_to(prev.range().start(), next.range().end())) |
98 | prev.range().start(), | ||
99 | next.range().end(), | ||
100 | )) | ||
101 | } else { | 99 | } else { |
102 | None | 100 | None |
103 | } | 101 | } |
@@ -109,7 +107,7 @@ fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef { | |||
109 | match node.kind() { | 107 | match node.kind() { |
110 | COMMENT => res = node, | 108 | COMMENT => res = node, |
111 | WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), | 109 | WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), |
112 | _ => break | 110 | _ => break, |
113 | } | 111 | } |
114 | } | 112 | } |
115 | res | 113 | res |
@@ -125,8 +123,7 @@ mod tests { | |||
125 | let file = File::parse(&before); | 123 | let file = File::parse(&before); |
126 | let mut range = TextRange::offset_len(cursor, 0.into()); | 124 | let mut range = TextRange::offset_len(cursor, 0.into()); |
127 | for &after in afters { | 125 | for &after in afters { |
128 | range = extend_selection(&file, range) | 126 | range = extend_selection(&file, range).unwrap(); |
129 | .unwrap(); | ||
130 | let actual = &before[range]; | 127 | let actual = &before[range]; |
131 | assert_eq!(after, actual); | 128 | assert_eq!(after, actual); |
132 | } | 129 | } |
@@ -134,10 +131,7 @@ mod tests { | |||
134 | 131 | ||
135 | #[test] | 132 | #[test] |
136 | fn test_extend_selection_arith() { | 133 | fn test_extend_selection_arith() { |
137 | do_check( | 134 | do_check(r#"fn foo() { <|>1 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]); |
138 | r#"fn foo() { <|>1 + 1 }"#, | ||
139 | &["1", "1 + 1", "{ 1 + 1 }"], | ||
140 | ); | ||
141 | } | 135 | } |
142 | 136 | ||
143 | #[test] | 137 | #[test] |
@@ -149,7 +143,7 @@ impl S { | |||
149 | 143 | ||
150 | } | 144 | } |
151 | }"#, | 145 | }"#, |
152 | &[" fn foo() {\n\n }\n"] | 146 | &[" fn foo() {\n\n }\n"], |
153 | ); | 147 | ); |
154 | } | 148 | } |
155 | 149 | ||
@@ -165,7 +159,11 @@ struct B { | |||
165 | <|> | 159 | <|> |
166 | } | 160 | } |
167 | "#, | 161 | "#, |
168 | &["\n \n", "{\n \n}", "/// bla\n/// bla\nstruct B {\n \n}"] | 162 | &[ |
163 | "\n \n", | ||
164 | "{\n \n}", | ||
165 | "/// bla\n/// bla\nstruct B {\n \n}", | ||
166 | ], | ||
169 | ) | 167 | ) |
170 | } | 168 | } |
171 | 169 | ||
@@ -181,7 +179,7 @@ fn bar(){} | |||
181 | 179 | ||
182 | // fn foo(){} | 180 | // fn foo(){} |
183 | "#, | 181 | "#, |
184 | &["// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"] | 182 | &["// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"], |
185 | ); | 183 | ); |
186 | } | 184 | } |
187 | 185 | ||
@@ -191,42 +189,34 @@ fn bar(){} | |||
191 | r#" | 189 | r#" |
192 | fn main() { foo<|>+bar;} | 190 | fn main() { foo<|>+bar;} |
193 | "#, | 191 | "#, |
194 | &["foo", "foo+bar"] | 192 | &["foo", "foo+bar"], |
195 | ); | 193 | ); |
196 | do_check( | 194 | do_check( |
197 | r#" | 195 | r#" |
198 | fn main() { foo+<|>bar;} | 196 | fn main() { foo+<|>bar;} |
199 | "#, | 197 | "#, |
200 | &["bar", "foo+bar"] | 198 | &["bar", "foo+bar"], |
201 | ); | 199 | ); |
202 | } | 200 | } |
203 | 201 | ||
204 | #[test] | 202 | #[test] |
205 | fn test_extend_selection_prefer_lifetimes() { | 203 | fn test_extend_selection_prefer_lifetimes() { |
206 | do_check( | 204 | do_check(r#"fn foo<<|>'a>() {}"#, &["'a", "<'a>"]); |
207 | r#"fn foo<<|>'a>() {}"#, | 205 | do_check(r#"fn foo<'a<|>>() {}"#, &["'a", "<'a>"]); |
208 | &["'a", "<'a>"] | ||
209 | ); | ||
210 | do_check( | ||
211 | r#"fn foo<'a<|>>() {}"#, | ||
212 | &["'a", "<'a>"] | ||
213 | ); | ||
214 | } | 206 | } |
215 | 207 | ||
216 | #[test] | 208 | #[test] |
217 | fn test_extend_selection_select_first_word() { | 209 | fn test_extend_selection_select_first_word() { |
210 | do_check(r#"// foo bar b<|>az quxx"#, &["baz", "// foo bar baz quxx"]); | ||
218 | do_check( | 211 | do_check( |
219 | r#"// foo bar b<|>az quxx"#, | 212 | r#" |
220 | &["baz", "// foo bar baz quxx"] | ||
221 | ); | ||
222 | do_check(r#" | ||
223 | impl S { | 213 | impl S { |
224 | fn foo() { | 214 | fn foo() { |
225 | // hel<|>lo world | 215 | // hel<|>lo world |
226 | } | 216 | } |
227 | } | 217 | } |
228 | "#, | 218 | "#, |
229 | &["hello", "// hello world"] | 219 | &["hello", "// hello world"], |
230 | ); | 220 | ); |
231 | } | 221 | } |
232 | } | 222 | } |