aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/assists/inline_local_variable.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-09-25 12:29:41 +0100
committerAleksey Kladov <[email protected]>2019-09-25 12:29:41 +0100
commitf32081fa185b3a9df021f277c2c27fbd123d0951 (patch)
tree0032bc2f09dc0f323ae5b77bbc2b7d891173f398 /crates/ra_assists/src/assists/inline_local_variable.rs
parentd9b4835625ac96c7628e2ef66ef6e26cc48d231f (diff)
move assists to subdir
Diffstat (limited to 'crates/ra_assists/src/assists/inline_local_variable.rs')
-rw-r--r--crates/ra_assists/src/assists/inline_local_variable.rs636
1 files changed, 636 insertions, 0 deletions
diff --git a/crates/ra_assists/src/assists/inline_local_variable.rs b/crates/ra_assists/src/assists/inline_local_variable.rs
new file mode 100644
index 000000000..eedb29199
--- /dev/null
+++ b/crates/ra_assists/src/assists/inline_local_variable.rs
@@ -0,0 +1,636 @@
1use hir::db::HirDatabase;
2use ra_syntax::{
3 ast::{self, AstNode, AstToken},
4 TextRange,
5};
6
7use crate::assist_ctx::AssistBuilder;
8use crate::{Assist, AssistCtx, AssistId};
9
10pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let let_stmt = ctx.node_at_offset::<ast::LetStmt>()?;
12 let bind_pat = match let_stmt.pat()? {
13 ast::Pat::BindPat(pat) => pat,
14 _ => return None,
15 };
16 if bind_pat.is_mutable() {
17 return None;
18 }
19 let initializer_expr = let_stmt.initializer()?;
20 let delete_range = if let Some(whitespace) = let_stmt
21 .syntax()
22 .next_sibling_or_token()
23 .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone()))
24 {
25 TextRange::from_to(
26 let_stmt.syntax().text_range().start(),
27 whitespace.syntax().text_range().end(),
28 )
29 } else {
30 let_stmt.syntax().text_range()
31 };
32 let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None);
33 let refs = analyzer.find_all_refs(&bind_pat);
34
35 let mut wrap_in_parens = vec![true; refs.len()];
36
37 for (i, desc) in refs.iter().enumerate() {
38 let usage_node = ctx
39 .covering_node_for_range(desc.range)
40 .ancestors()
41 .find_map(|node| ast::PathExpr::cast(node))?;
42 let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast);
43 let usage_parent = match usage_parent_option {
44 Some(u) => u,
45 None => {
46 wrap_in_parens[i] = false;
47 continue;
48 }
49 };
50
51 wrap_in_parens[i] = match (&initializer_expr, usage_parent) {
52 (ast::Expr::CallExpr(_), _)
53 | (ast::Expr::IndexExpr(_), _)
54 | (ast::Expr::MethodCallExpr(_), _)
55 | (ast::Expr::FieldExpr(_), _)
56 | (ast::Expr::TryExpr(_), _)
57 | (ast::Expr::RefExpr(_), _)
58 | (ast::Expr::Literal(_), _)
59 | (ast::Expr::TupleExpr(_), _)
60 | (ast::Expr::ArrayExpr(_), _)
61 | (ast::Expr::ParenExpr(_), _)
62 | (ast::Expr::PathExpr(_), _)
63 | (ast::Expr::BlockExpr(_), _)
64 | (_, ast::Expr::CallExpr(_))
65 | (_, ast::Expr::TupleExpr(_))
66 | (_, ast::Expr::ArrayExpr(_))
67 | (_, ast::Expr::ParenExpr(_))
68 | (_, ast::Expr::ForExpr(_))
69 | (_, ast::Expr::WhileExpr(_))
70 | (_, ast::Expr::BreakExpr(_))
71 | (_, ast::Expr::ReturnExpr(_))
72 | (_, ast::Expr::MatchExpr(_)) => false,
73 _ => true,
74 };
75 }
76
77 let init_str = initializer_expr.syntax().text().to_string();
78 let init_in_paren = format!("({})", &init_str);
79
80 ctx.add_action(
81 AssistId("inline_local_variable"),
82 "inline local variable",
83 move |edit: &mut AssistBuilder| {
84 edit.delete(delete_range);
85 for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) {
86 if should_wrap {
87 edit.replace(desc.range, init_in_paren.clone())
88 } else {
89 edit.replace(desc.range, init_str.clone())
90 }
91 }
92 edit.set_cursor(delete_range.start())
93 },
94 );
95
96 ctx.build()
97}
98
99#[cfg(test)]
100mod tests {
101 use crate::helpers::{check_assist, check_assist_not_applicable};
102
103 use super::*;
104
105 #[test]
106 fn test_inline_let_bind_literal_expr() {
107 check_assist(
108 inline_local_varialbe,
109 "
110fn bar(a: usize) {}
111fn foo() {
112 let a<|> = 1;
113 a + 1;
114 if a > 10 {
115 }
116
117 while a > 10 {
118
119 }
120 let b = a * 10;
121 bar(a);
122}",
123 "
124fn bar(a: usize) {}
125fn foo() {
126 <|>1 + 1;
127 if 1 > 10 {
128 }
129
130 while 1 > 10 {
131
132 }
133 let b = 1 * 10;
134 bar(1);
135}",
136 );
137 }
138
139 #[test]
140 fn test_inline_let_bind_bin_expr() {
141 check_assist(
142 inline_local_varialbe,
143 "
144fn bar(a: usize) {}
145fn foo() {
146 let a<|> = 1 + 1;
147 a + 1;
148 if a > 10 {
149 }
150
151 while a > 10 {
152
153 }
154 let b = a * 10;
155 bar(a);
156}",
157 "
158fn bar(a: usize) {}
159fn foo() {
160 <|>(1 + 1) + 1;
161 if (1 + 1) > 10 {
162 }
163
164 while (1 + 1) > 10 {
165
166 }
167 let b = (1 + 1) * 10;
168 bar(1 + 1);
169}",
170 );
171 }
172
173 #[test]
174 fn test_inline_let_bind_function_call_expr() {
175 check_assist(
176 inline_local_varialbe,
177 "
178fn bar(a: usize) {}
179fn foo() {
180 let a<|> = bar(1);
181 a + 1;
182 if a > 10 {
183 }
184
185 while a > 10 {
186
187 }
188 let b = a * 10;
189 bar(a);
190}",
191 "
192fn bar(a: usize) {}
193fn foo() {
194 <|>bar(1) + 1;
195 if bar(1) > 10 {
196 }
197
198 while bar(1) > 10 {
199
200 }
201 let b = bar(1) * 10;
202 bar(bar(1));
203}",
204 );
205 }
206
207 #[test]
208 fn test_inline_let_bind_cast_expr() {
209 check_assist(
210 inline_local_varialbe,
211 "
212fn bar(a: usize): usize { a }
213fn foo() {
214 let a<|> = bar(1) as u64;
215 a + 1;
216 if a > 10 {
217 }
218
219 while a > 10 {
220
221 }
222 let b = a * 10;
223 bar(a);
224}",
225 "
226fn bar(a: usize): usize { a }
227fn foo() {
228 <|>(bar(1) as u64) + 1;
229 if (bar(1) as u64) > 10 {
230 }
231
232 while (bar(1) as u64) > 10 {
233
234 }
235 let b = (bar(1) as u64) * 10;
236 bar(bar(1) as u64);
237}",
238 );
239 }
240
241 #[test]
242 fn test_inline_let_bind_block_expr() {
243 check_assist(
244 inline_local_varialbe,
245 "
246fn foo() {
247 let a<|> = { 10 + 1 };
248 a + 1;
249 if a > 10 {
250 }
251
252 while a > 10 {
253
254 }
255 let b = a * 10;
256 bar(a);
257}",
258 "
259fn foo() {
260 <|>{ 10 + 1 } + 1;
261 if { 10 + 1 } > 10 {
262 }
263
264 while { 10 + 1 } > 10 {
265
266 }
267 let b = { 10 + 1 } * 10;
268 bar({ 10 + 1 });
269}",
270 );
271 }
272
273 #[test]
274 fn test_inline_let_bind_paren_expr() {
275 check_assist(
276 inline_local_varialbe,
277 "
278fn foo() {
279 let a<|> = ( 10 + 1 );
280 a + 1;
281 if a > 10 {
282 }
283
284 while a > 10 {
285
286 }
287 let b = a * 10;
288 bar(a);
289}",
290 "
291fn foo() {
292 <|>( 10 + 1 ) + 1;
293 if ( 10 + 1 ) > 10 {
294 }
295
296 while ( 10 + 1 ) > 10 {
297
298 }
299 let b = ( 10 + 1 ) * 10;
300 bar(( 10 + 1 ));
301}",
302 );
303 }
304
305 #[test]
306 fn test_not_inline_mut_variable() {
307 check_assist_not_applicable(
308 inline_local_varialbe,
309 "
310fn foo() {
311 let mut a<|> = 1 + 1;
312 a + 1;
313}",
314 );
315 }
316
317 #[test]
318 fn test_call_expr() {
319 check_assist(
320 inline_local_varialbe,
321 "
322fn foo() {
323 let a<|> = bar(10 + 1);
324 let b = a * 10;
325 let c = a as usize;
326}",
327 "
328fn foo() {
329 <|>let b = bar(10 + 1) * 10;
330 let c = bar(10 + 1) as usize;
331}",
332 );
333 }
334
335 #[test]
336 fn test_index_expr() {
337 check_assist(
338 inline_local_varialbe,
339 "
340fn foo() {
341 let x = vec![1, 2, 3];
342 let a<|> = x[0];
343 let b = a * 10;
344 let c = a as usize;
345}",
346 "
347fn foo() {
348 let x = vec![1, 2, 3];
349 <|>let b = x[0] * 10;
350 let c = x[0] as usize;
351}",
352 );
353 }
354
355 #[test]
356 fn test_method_call_expr() {
357 check_assist(
358 inline_local_varialbe,
359 "
360fn foo() {
361 let bar = vec![1];
362 let a<|> = bar.len();
363 let b = a * 10;
364 let c = a as usize;
365}",
366 "
367fn foo() {
368 let bar = vec![1];
369 <|>let b = bar.len() * 10;
370 let c = bar.len() as usize;
371}",
372 );
373 }
374
375 #[test]
376 fn test_field_expr() {
377 check_assist(
378 inline_local_varialbe,
379 "
380struct Bar {
381 foo: usize
382}
383
384fn foo() {
385 let bar = Bar { foo: 1 };
386 let a<|> = bar.foo;
387 let b = a * 10;
388 let c = a as usize;
389}",
390 "
391struct Bar {
392 foo: usize
393}
394
395fn foo() {
396 let bar = Bar { foo: 1 };
397 <|>let b = bar.foo * 10;
398 let c = bar.foo as usize;
399}",
400 );
401 }
402
403 #[test]
404 fn test_try_expr() {
405 check_assist(
406 inline_local_varialbe,
407 "
408fn foo() -> Option<usize> {
409 let bar = Some(1);
410 let a<|> = bar?;
411 let b = a * 10;
412 let c = a as usize;
413 None
414}",
415 "
416fn foo() -> Option<usize> {
417 let bar = Some(1);
418 <|>let b = bar? * 10;
419 let c = bar? as usize;
420 None
421}",
422 );
423 }
424
425 #[test]
426 fn test_ref_expr() {
427 check_assist(
428 inline_local_varialbe,
429 "
430fn foo() {
431 let bar = 10;
432 let a<|> = &bar;
433 let b = a * 10;
434}",
435 "
436fn foo() {
437 let bar = 10;
438 <|>let b = &bar * 10;
439}",
440 );
441 }
442
443 #[test]
444 fn test_tuple_expr() {
445 check_assist(
446 inline_local_varialbe,
447 "
448fn foo() {
449 let a<|> = (10, 20);
450 let b = a[0];
451}",
452 "
453fn foo() {
454 <|>let b = (10, 20)[0];
455}",
456 );
457 }
458
459 #[test]
460 fn test_array_expr() {
461 check_assist(
462 inline_local_varialbe,
463 "
464fn foo() {
465 let a<|> = [1, 2, 3];
466 let b = a.len();
467}",
468 "
469fn foo() {
470 <|>let b = [1, 2, 3].len();
471}",
472 );
473 }
474
475 #[test]
476 fn test_paren() {
477 check_assist(
478 inline_local_varialbe,
479 "
480fn foo() {
481 let a<|> = (10 + 20);
482 let b = a * 10;
483 let c = a as usize;
484}",
485 "
486fn foo() {
487 <|>let b = (10 + 20) * 10;
488 let c = (10 + 20) as usize;
489}",
490 );
491 }
492
493 #[test]
494 fn test_path_expr() {
495 check_assist(
496 inline_local_varialbe,
497 "
498fn foo() {
499 let d = 10;
500 let a<|> = d;
501 let b = a * 10;
502 let c = a as usize;
503}",
504 "
505fn foo() {
506 let d = 10;
507 <|>let b = d * 10;
508 let c = d as usize;
509}",
510 );
511 }
512
513 #[test]
514 fn test_block_expr() {
515 check_assist(
516 inline_local_varialbe,
517 "
518fn foo() {
519 let a<|> = { 10 };
520 let b = a * 10;
521 let c = a as usize;
522}",
523 "
524fn foo() {
525 <|>let b = { 10 } * 10;
526 let c = { 10 } as usize;
527}",
528 );
529 }
530
531 #[test]
532 fn test_used_in_different_expr1() {
533 check_assist(
534 inline_local_varialbe,
535 "
536fn foo() {
537 let a<|> = 10 + 20;
538 let b = a * 10;
539 let c = (a, 20);
540 let d = [a, 10];
541 let e = (a);
542}",
543 "
544fn foo() {
545 <|>let b = (10 + 20) * 10;
546 let c = (10 + 20, 20);
547 let d = [10 + 20, 10];
548 let e = (10 + 20);
549}",
550 );
551 }
552
553 #[test]
554 fn test_used_in_for_expr() {
555 check_assist(
556 inline_local_varialbe,
557 "
558fn foo() {
559 let a<|> = vec![10, 20];
560 for i in a {}
561}",
562 "
563fn foo() {
564 <|>for i in vec![10, 20] {}
565}",
566 );
567 }
568
569 #[test]
570 fn test_used_in_while_expr() {
571 check_assist(
572 inline_local_varialbe,
573 "
574fn foo() {
575 let a<|> = 1 > 0;
576 while a {}
577}",
578 "
579fn foo() {
580 <|>while 1 > 0 {}
581}",
582 );
583 }
584
585 #[test]
586 fn test_used_in_break_expr() {
587 check_assist(
588 inline_local_varialbe,
589 "
590fn foo() {
591 let a<|> = 1 + 1;
592 loop {
593 break a;
594 }
595}",
596 "
597fn foo() {
598 <|>loop {
599 break 1 + 1;
600 }
601}",
602 );
603 }
604
605 #[test]
606 fn test_used_in_return_expr() {
607 check_assist(
608 inline_local_varialbe,
609 "
610fn foo() {
611 let a<|> = 1 > 0;
612 return a;
613}",
614 "
615fn foo() {
616 <|>return 1 > 0;
617}",
618 );
619 }
620
621 #[test]
622 fn test_used_in_match_expr() {
623 check_assist(
624 inline_local_varialbe,
625 "
626fn foo() {
627 let a<|> = 1 > 0;
628 match a {}
629}",
630 "
631fn foo() {
632 <|>match 1 > 0 {}
633}",
634 );
635 }
636}