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