aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api_light
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api_light')
-rw-r--r--crates/ra_ide_api_light/src/join_lines.rs149
1 files changed, 147 insertions, 2 deletions
diff --git a/crates/ra_ide_api_light/src/join_lines.rs b/crates/ra_ide_api_light/src/join_lines.rs
index 949ee1544..9f59fbd43 100644
--- a/crates/ra_ide_api_light/src/join_lines.rs
+++ b/crates/ra_ide_api_light/src/join_lines.rs
@@ -120,11 +120,47 @@ fn remove_newline(
120 } 120 }
121} 121}
122 122
123/// fixes a comma after the given expression and optionally inserts a new trailing comma
124/// if no comma was found and `comma_offset` is provided
125fn fix_comma_after(edit: &mut TextEditBuilder, node: &SyntaxNode, comma_offset: Option<TextUnit>) {
126 let next = node.next_sibling();
127 let nnext = node.next_sibling().and_then(|n| n.next_sibling());
128
129 match (next, nnext) {
130 // Whitespace followed by a comma
131 // remove the whitespace
132 (Some(ws), Some(comma)) if ws.kind() == WHITESPACE && comma.kind() == COMMA => {
133 edit.delete(ws.range());
134 }
135
136 // if we are not a comma and if comma_offset was provided,
137 // insert trailing comma after the block
138 (Some(n), _) if n.kind() != COMMA => {
139 if let Some(comma_offset) = comma_offset {
140 edit.insert(comma_offset, ",".to_owned());
141 }
142 }
143
144 _ => {}
145 }
146}
147
123fn join_single_expr_block(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> { 148fn join_single_expr_block(edit: &mut TextEditBuilder, node: &SyntaxNode) -> Option<()> {
124 let block = ast::Block::cast(node.parent()?)?; 149 let block = ast::Block::cast(node.parent()?)?;
125 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; 150 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
126 let expr = extract_trivial_expression(block)?; 151 let expr = extract_trivial_expression(block)?;
127 edit.replace(block_expr.syntax().range(), expr.syntax().text().to_string()); 152
153 let block_range = block_expr.syntax().range();
154 edit.replace(block_range, expr.syntax().text().to_string());
155
156 // Match block needs to have a comma after the block
157 // otherwise we'll maintain a comma after the block if such existed
158 // but we remove excess whitespace between the expression and the comma.
159 if let Some(match_arm) = block_expr.syntax().parent().and_then(ast::MatchArm::cast) {
160 fix_comma_after(edit, match_arm.syntax(), Some(block_range.end()));
161 } else {
162 fix_comma_after(edit, block_expr.syntax(), None);
163 }
128 Some(()) 164 Some(())
129} 165}
130 166
@@ -208,7 +244,6 @@ fn foo() {
208 } 244 }
209 245
210 #[test] 246 #[test]
211 #[ignore] // FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/868
212 fn join_lines_adds_comma_for_block_in_match_arm() { 247 fn join_lines_adds_comma_for_block_in_match_arm() {
213 check_join_lines( 248 check_join_lines(
214 r" 249 r"
@@ -231,6 +266,116 @@ fn foo(e: Result<U, V>) {
231 } 266 }
232 267
233 #[test] 268 #[test]
269 fn join_lines_keeps_comma_for_block_in_match_arm() {
270 // We already have a comma
271 check_join_lines(
272 r"
273fn foo(e: Result<U, V>) {
274 match e {
275 Ok(u) => <|>{
276 u.foo()
277 },
278 Err(v) => v,
279 }
280}",
281 r"
282fn foo(e: Result<U, V>) {
283 match e {
284 Ok(u) => <|>u.foo(),
285 Err(v) => v,
286 }
287}",
288 );
289
290 // comma with whitespace between brace and ,
291 check_join_lines(
292 r"
293fn foo(e: Result<U, V>) {
294 match e {
295 Ok(u) => <|>{
296 u.foo()
297 } ,
298 Err(v) => v,
299 }
300}",
301 r"
302fn foo(e: Result<U, V>) {
303 match e {
304 Ok(u) => <|>u.foo(),
305 Err(v) => v,
306 }
307}",
308 );
309
310 // comma with newline between brace and ,
311 check_join_lines(
312 r"
313fn foo(e: Result<U, V>) {
314 match e {
315 Ok(u) => <|>{
316 u.foo()
317 }
318 ,
319 Err(v) => v,
320 }
321}",
322 r"
323fn foo(e: Result<U, V>) {
324 match e {
325 Ok(u) => <|>u.foo(),
326 Err(v) => v,
327 }
328}",
329 );
330 }
331
332 #[test]
333 fn join_lines_keeps_comma_with_single_arg_tuple() {
334 // A single arg tuple
335 check_join_lines(
336 r"
337fn foo() {
338 let x = (<|>{
339 4
340 },);
341}",
342 r"
343fn foo() {
344 let x = (<|>4,);
345}",
346 );
347
348 // single arg tuple with whitespace between brace and comma
349 check_join_lines(
350 r"
351fn foo() {
352 let x = (<|>{
353 4
354 } ,);
355}",
356 r"
357fn foo() {
358 let x = (<|>4,);
359}",
360 );
361
362 // single arg tuple with newline between brace and comma
363 check_join_lines(
364 r"
365fn foo() {
366 let x = (<|>{
367 4
368 }
369 ,);
370}",
371 r"
372fn foo() {
373 let x = (<|>4,);
374}",
375 );
376 }
377
378 #[test]
234 fn test_join_lines_use_items_left() { 379 fn test_join_lines_use_items_left() {
235 // No space after the '{' 380 // No space after the '{'
236 check_join_lines( 381 check_join_lines(