diff options
Diffstat (limited to 'crates/ra_assists/src/handlers/extract_variable.rs')
-rw-r--r-- | crates/ra_assists/src/handlers/extract_variable.rs | 137 |
1 files changed, 71 insertions, 66 deletions
diff --git a/crates/ra_assists/src/handlers/extract_variable.rs b/crates/ra_assists/src/handlers/extract_variable.rs index c4150d2bb..481baf1a4 100644 --- a/crates/ra_assists/src/handlers/extract_variable.rs +++ b/crates/ra_assists/src/handlers/extract_variable.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::{ | |||
9 | use stdx::format_to; | 9 | use stdx::format_to; |
10 | use test_utils::mark; | 10 | use test_utils::mark; |
11 | 11 | ||
12 | use crate::{AssistContext, AssistId, Assists}; | 12 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
13 | 13 | ||
14 | // Assist: extract_variable | 14 | // Assist: extract_variable |
15 | // | 15 | // |
@@ -43,80 +43,85 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
43 | return None; | 43 | return None; |
44 | } | 44 | } |
45 | let target = expr.syntax().text_range(); | 45 | let target = expr.syntax().text_range(); |
46 | acc.add(AssistId("extract_variable"), "Extract into variable", target, move |edit| { | 46 | acc.add( |
47 | let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { | 47 | AssistId("extract_variable", AssistKind::RefactorExtract), |
48 | Some(field) => field.name_ref(), | 48 | "Extract into variable", |
49 | None => None, | 49 | target, |
50 | }; | 50 | move |edit| { |
51 | 51 | let field_shorthand = match expr.syntax().parent().and_then(ast::RecordField::cast) { | |
52 | let mut buf = String::new(); | 52 | Some(field) => field.name_ref(), |
53 | 53 | None => None, | |
54 | let var_name = match &field_shorthand { | 54 | }; |
55 | Some(it) => it.to_string(), | 55 | |
56 | None => "var_name".to_string(), | 56 | let mut buf = String::new(); |
57 | }; | 57 | |
58 | let expr_range = match &field_shorthand { | 58 | let var_name = match &field_shorthand { |
59 | Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), | 59 | Some(it) => it.to_string(), |
60 | None => expr.syntax().text_range(), | 60 | None => "var_name".to_string(), |
61 | }; | 61 | }; |
62 | 62 | let expr_range = match &field_shorthand { | |
63 | if wrap_in_block { | 63 | Some(it) => it.syntax().text_range().cover(expr.syntax().text_range()), |
64 | format_to!(buf, "{{ let {} = ", var_name); | 64 | None => expr.syntax().text_range(), |
65 | } else { | 65 | }; |
66 | format_to!(buf, "let {} = ", var_name); | 66 | |
67 | }; | 67 | if wrap_in_block { |
68 | format_to!(buf, "{}", expr.syntax()); | 68 | format_to!(buf, "{{ let {} = ", var_name); |
69 | 69 | } else { | |
70 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); | 70 | format_to!(buf, "let {} = ", var_name); |
71 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { | 71 | }; |
72 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) | 72 | format_to!(buf, "{}", expr.syntax()); |
73 | } else { | 73 | |
74 | false | 74 | let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); |
75 | }; | 75 | let is_full_stmt = if let Some(expr_stmt) = &full_stmt { |
76 | if is_full_stmt { | 76 | Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) |
77 | mark::hit!(test_extract_var_expr_stmt); | 77 | } else { |
78 | if full_stmt.unwrap().semicolon_token().is_none() { | 78 | false |
79 | buf.push_str(";"); | 79 | }; |
80 | if is_full_stmt { | ||
81 | mark::hit!(test_extract_var_expr_stmt); | ||
82 | if full_stmt.unwrap().semicolon_token().is_none() { | ||
83 | buf.push_str(";"); | ||
84 | } | ||
85 | match ctx.config.snippet_cap { | ||
86 | Some(cap) => { | ||
87 | let snip = buf | ||
88 | .replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); | ||
89 | edit.replace_snippet(cap, expr_range, snip) | ||
90 | } | ||
91 | None => edit.replace(expr_range, buf), | ||
92 | } | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | buf.push_str(";"); | ||
97 | |||
98 | // We want to maintain the indent level, | ||
99 | // but we do not want to duplicate possible | ||
100 | // extra newlines in the indent block | ||
101 | let text = indent.text(); | ||
102 | if text.starts_with('\n') { | ||
103 | buf.push_str("\n"); | ||
104 | buf.push_str(text.trim_start_matches('\n')); | ||
105 | } else { | ||
106 | buf.push_str(text); | ||
80 | } | 107 | } |
108 | |||
109 | edit.replace(expr_range, var_name.clone()); | ||
110 | let offset = anchor_stmt.text_range().start(); | ||
81 | match ctx.config.snippet_cap { | 111 | match ctx.config.snippet_cap { |
82 | Some(cap) => { | 112 | Some(cap) => { |
83 | let snip = | 113 | let snip = |
84 | buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); | 114 | buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); |
85 | edit.replace_snippet(cap, expr_range, snip) | 115 | edit.insert_snippet(cap, offset, snip) |
86 | } | 116 | } |
87 | None => edit.replace(expr_range, buf), | 117 | None => edit.insert(offset, buf), |
88 | } | 118 | } |
89 | return; | ||
90 | } | ||
91 | 119 | ||
92 | buf.push_str(";"); | 120 | if wrap_in_block { |
93 | 121 | edit.insert(anchor_stmt.text_range().end(), " }"); | |
94 | // We want to maintain the indent level, | ||
95 | // but we do not want to duplicate possible | ||
96 | // extra newlines in the indent block | ||
97 | let text = indent.text(); | ||
98 | if text.starts_with('\n') { | ||
99 | buf.push_str("\n"); | ||
100 | buf.push_str(text.trim_start_matches('\n')); | ||
101 | } else { | ||
102 | buf.push_str(text); | ||
103 | } | ||
104 | |||
105 | edit.replace(expr_range, var_name.clone()); | ||
106 | let offset = anchor_stmt.text_range().start(); | ||
107 | match ctx.config.snippet_cap { | ||
108 | Some(cap) => { | ||
109 | let snip = | ||
110 | buf.replace(&format!("let {}", var_name), &format!("let $0{}", var_name)); | ||
111 | edit.insert_snippet(cap, offset, snip) | ||
112 | } | 122 | } |
113 | None => edit.insert(offset, buf), | 123 | }, |
114 | } | 124 | ) |
115 | |||
116 | if wrap_in_block { | ||
117 | edit.insert(anchor_stmt.text_range().end(), " }"); | ||
118 | } | ||
119 | }) | ||
120 | } | 125 | } |
121 | 126 | ||
122 | /// Check whether the node is a valid expression which can be extracted to a variable. | 127 | /// Check whether the node is a valid expression which can be extracted to a variable. |