diff options
Diffstat (limited to 'crates/libeditor/src')
-rw-r--r-- | crates/libeditor/src/code_actions.rs | 1 | ||||
-rw-r--r-- | crates/libeditor/src/edit.rs | 12 | ||||
-rw-r--r-- | crates/libeditor/src/typing.rs | 69 |
3 files changed, 37 insertions, 45 deletions
diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs index dadbd63ab..522b605ed 100644 --- a/crates/libeditor/src/code_actions.rs +++ b/crates/libeditor/src/code_actions.rs | |||
@@ -13,7 +13,6 @@ use libsyntax2::{ | |||
13 | 13 | ||
14 | use {EditBuilder, Edit, find_node_at_offset}; | 14 | use {EditBuilder, Edit, find_node_at_offset}; |
15 | 15 | ||
16 | // TODO: rename to FileEdit | ||
17 | #[derive(Debug)] | 16 | #[derive(Debug)] |
18 | pub struct LocalEdit { | 17 | pub struct LocalEdit { |
19 | pub edit: Edit, | 18 | pub edit: Edit, |
diff --git a/crates/libeditor/src/edit.rs b/crates/libeditor/src/edit.rs index dcf1ee81e..09cf2bd00 100644 --- a/crates/libeditor/src/edit.rs +++ b/crates/libeditor/src/edit.rs | |||
@@ -1,5 +1,8 @@ | |||
1 | use {TextRange, TextUnit}; | 1 | use {TextRange, TextUnit}; |
2 | use libsyntax2::AtomEdit; | 2 | use libsyntax2::{ |
3 | AtomEdit, | ||
4 | text_utils::contains_offset_nonstrict, | ||
5 | }; | ||
3 | 6 | ||
4 | #[derive(Debug, Clone)] | 7 | #[derive(Debug, Clone)] |
5 | pub struct Edit { | 8 | pub struct Edit { |
@@ -15,19 +18,15 @@ impl EditBuilder { | |||
15 | pub fn new() -> EditBuilder { | 18 | pub fn new() -> EditBuilder { |
16 | EditBuilder { atoms: Vec::new() } | 19 | EditBuilder { atoms: Vec::new() } |
17 | } | 20 | } |
18 | |||
19 | pub fn replace(&mut self, range: TextRange, replace_with: String) { | 21 | pub fn replace(&mut self, range: TextRange, replace_with: String) { |
20 | self.atoms.push(AtomEdit::replace(range, replace_with)) | 22 | self.atoms.push(AtomEdit::replace(range, replace_with)) |
21 | } | 23 | } |
22 | |||
23 | pub fn delete(&mut self, range: TextRange) { | 24 | pub fn delete(&mut self, range: TextRange) { |
24 | self.atoms.push(AtomEdit::delete(range)) | 25 | self.atoms.push(AtomEdit::delete(range)) |
25 | } | 26 | } |
26 | |||
27 | pub fn insert(&mut self, offset: TextUnit, text: String) { | 27 | pub fn insert(&mut self, offset: TextUnit, text: String) { |
28 | self.atoms.push(AtomEdit::insert(offset, text)) | 28 | self.atoms.push(AtomEdit::insert(offset, text)) |
29 | } | 29 | } |
30 | |||
31 | pub fn finish(self) -> Edit { | 30 | pub fn finish(self) -> Edit { |
32 | let mut atoms = self.atoms; | 31 | let mut atoms = self.atoms; |
33 | atoms.sort_by_key(|a| a.delete.start()); | 32 | atoms.sort_by_key(|a| a.delete.start()); |
@@ -36,6 +35,9 @@ impl EditBuilder { | |||
36 | } | 35 | } |
37 | Edit { atoms } | 36 | Edit { atoms } |
38 | } | 37 | } |
38 | pub fn invalidates_offset(&self, offset: TextUnit) -> bool { | ||
39 | self.atoms.iter().any(|atom| contains_offset_nonstrict(atom.delete, offset)) | ||
40 | } | ||
39 | } | 41 | } |
40 | 42 | ||
41 | impl Edit { | 43 | impl Edit { |
diff --git a/crates/libeditor/src/typing.rs b/crates/libeditor/src/typing.rs index f888f3240..826b16181 100644 --- a/crates/libeditor/src/typing.rs +++ b/crates/libeditor/src/typing.rs | |||
@@ -45,10 +45,11 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { | |||
45 | for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { | 45 | for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { |
46 | let pos: TextUnit = (pos as u32).into(); | 46 | let pos: TextUnit = (pos as u32).into(); |
47 | let off = node.range().start() + range.start() + pos; | 47 | let off = node.range().start() + range.start() + pos; |
48 | remove_newline(&mut edit, node, text.as_str(), off); | 48 | if !edit.invalidates_offset(off) { |
49 | remove_newline(&mut edit, node, text.as_str(), off); | ||
50 | } | ||
49 | } | 51 | } |
50 | } | 52 | } |
51 | eprintln!("{:?}", edit); | ||
52 | 53 | ||
53 | LocalEdit { | 54 | LocalEdit { |
54 | edit: edit.finish(), | 55 | edit: edit.finish(), |
@@ -239,17 +240,17 @@ fn foo() { | |||
239 | }"); | 240 | }"); |
240 | } | 241 | } |
241 | 242 | ||
242 | #[test] | 243 | fn check_join_lines_sel(before: &str, after: &str) { |
243 | fn test_join_lines_selection() { | 244 | let (sel, before) = extract_range(before); |
244 | fn do_check(before: &str, after: &str) { | 245 | let file = File::parse(&before); |
245 | let (sel, before) = extract_range(before); | 246 | let result = join_lines(&file, sel); |
246 | let file = File::parse(&before); | 247 | let actual = result.edit.apply(&before); |
247 | let result = join_lines(&file, sel); | 248 | assert_eq_text!(after, &actual); |
248 | let actual = result.edit.apply(&before); | 249 | } |
249 | assert_eq_text!(after, &actual); | ||
250 | } | ||
251 | 250 | ||
252 | do_check(r" | 251 | #[test] |
252 | fn test_join_lines_selection_fn_args() { | ||
253 | check_join_lines_sel(r" | ||
253 | fn foo() { | 254 | fn foo() { |
254 | <|>foo(1, | 255 | <|>foo(1, |
255 | 2, | 256 | 2, |
@@ -261,15 +262,22 @@ fn foo() { | |||
261 | foo(1, 2, 3) | 262 | foo(1, 2, 3) |
262 | } | 263 | } |
263 | "); | 264 | "); |
265 | } | ||
264 | 266 | ||
265 | do_check(r" | 267 | #[test] |
268 | fn test_join_lines_selection_struct() { | ||
269 | check_join_lines_sel(r" | ||
266 | struct Foo <|>{ | 270 | struct Foo <|>{ |
267 | f: u32, | 271 | f: u32, |
268 | }<|> | 272 | }<|> |
269 | ", r" | 273 | ", r" |
270 | struct Foo { f: u32 } | 274 | struct Foo { f: u32 } |
271 | "); | 275 | "); |
272 | do_check(r" | 276 | } |
277 | |||
278 | #[test] | ||
279 | fn test_join_lines_selection_dot_chain() { | ||
280 | check_join_lines_sel(r" | ||
273 | fn foo() { | 281 | fn foo() { |
274 | join(<|>type_params.type_params() | 282 | join(<|>type_params.type_params() |
275 | .filter_map(|it| it.name()) | 283 | .filter_map(|it| it.name()) |
@@ -278,39 +286,22 @@ fn foo() { | |||
278 | fn foo() { | 286 | fn foo() { |
279 | join(type_params.type_params().filter_map(|it| it.name()).map(|it| it.text())) | 287 | join(type_params.type_params().filter_map(|it| it.name()).map(|it| it.text())) |
280 | }"); | 288 | }"); |
289 | } | ||
281 | 290 | ||
282 | do_check(r" | 291 | #[test] |
283 | pub fn handle_find_matching_brace( | 292 | fn test_join_lines_selection_lambda_block_body() { |
284 | world: ServerWorld, | 293 | check_join_lines_sel(r" |
285 | params: req::FindMatchingBraceParams, | 294 | pub fn handle_find_matching_brace() { |
286 | ) -> Result<Vec<Position>> { | 295 | params.offsets |
287 | let file_id = params.text_document.try_conv_with(&world)?; | ||
288 | let file = world.analysis().file_syntax(file_id); | ||
289 | let line_index = world.analysis().file_line_index(file_id); | ||
290 | let res = params.offsets | ||
291 | .into_iter() | ||
292 | .map_conv_with(&line_index) | ||
293 | .map(|offset| <|>{ | 296 | .map(|offset| <|>{ |
294 | world.analysis().matching_brace(&file, offset).unwrap_or(offset) | 297 | world.analysis().matching_brace(&file, offset).unwrap_or(offset) |
295 | }<|>) | 298 | }<|>) |
296 | .map_conv_with(&line_index) | ||
297 | .collect(); | 299 | .collect(); |
298 | Ok(res) | ||
299 | }", r" | 300 | }", r" |
300 | pub fn handle_find_matching_brace( | 301 | pub fn handle_find_matching_brace() { |
301 | world: ServerWorld, | 302 | params.offsets |
302 | params: req::FindMatchingBraceParams, | ||
303 | ) -> Result<Vec<Position>> { | ||
304 | let file_id = params.text_document.try_conv_with(&world)?; | ||
305 | let file = world.analysis().file_syntax(file_id); | ||
306 | let line_index = world.analysis().file_line_index(file_id); | ||
307 | let res = params.offsets | ||
308 | .into_iter() | ||
309 | .map_conv_with(&line_index) | ||
310 | .map(|offset| world.analysis().matching_brace(&file, offset).unwrap_or(offset)) | 303 | .map(|offset| world.analysis().matching_brace(&file, offset).unwrap_or(offset)) |
311 | .map_conv_with(&line_index) | ||
312 | .collect(); | 304 | .collect(); |
313 | Ok(res) | ||
314 | }"); | 305 | }"); |
315 | } | 306 | } |
316 | 307 | ||