aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-29 16:35:28 +0100
committerAleksey Kladov <[email protected]>2018-08-29 16:35:28 +0100
commit7d95d38ecb9b197721e2533ba98afbc2f91610d0 (patch)
tree51cf2370f95dedc1d7434be1b708e4afa0c7bf7f /crates/libeditor
parent09ea0ca7e5fb5d3e123dc38927b158c798b689ad (diff)
fix join lines selection
Diffstat (limited to 'crates/libeditor')
-rw-r--r--crates/libeditor/src/code_actions.rs1
-rw-r--r--crates/libeditor/src/edit.rs12
-rw-r--r--crates/libeditor/src/typing.rs69
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
14use {EditBuilder, Edit, find_node_at_offset}; 14use {EditBuilder, Edit, find_node_at_offset};
15 15
16// TODO: rename to FileEdit
17#[derive(Debug)] 16#[derive(Debug)]
18pub struct LocalEdit { 17pub 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 @@
1use {TextRange, TextUnit}; 1use {TextRange, TextUnit};
2use libsyntax2::AtomEdit; 2use libsyntax2::{
3 AtomEdit,
4 text_utils::contains_offset_nonstrict,
5};
3 6
4#[derive(Debug, Clone)] 7#[derive(Debug, Clone)]
5pub struct Edit { 8pub 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
41impl Edit { 43impl 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"
253fn foo() { 254fn 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"
266struct Foo <|>{ 270struct Foo <|>{
267 f: u32, 271 f: u32,
268}<|> 272}<|>
269 ", r" 273 ", r"
270struct Foo { f: u32 } 274struct 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"
273fn foo() { 281fn 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() {
278fn foo() { 286fn 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]
283pub 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, 294pub 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"
300pub fn handle_find_matching_brace( 301pub 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