@@ -29,22 +29,31 @@ use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists};
2929// }
3030// ```
3131pub ( crate ) fn extract_variable ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
32- if ctx. has_empty_selection ( ) {
33- return None ;
34- }
35-
36- let node = match ctx. covering_element ( ) {
37- NodeOrToken :: Node ( it) => it,
38- NodeOrToken :: Token ( it) if it. kind ( ) == COMMENT => {
39- cov_mark:: hit!( extract_var_in_comment_is_not_applicable) ;
32+ let node = if ctx. has_empty_selection ( ) {
33+ if let Some ( expr_stmt) = ctx. find_node_at_offset :: < ast:: ExprStmt > ( ) {
34+ expr_stmt. syntax ( ) . clone ( )
35+ } else if let Some ( expr) = ctx. find_node_at_offset :: < ast:: Expr > ( ) {
36+ expr. syntax ( ) . ancestors ( ) . find_map ( valid_target_expr) ?. syntax ( ) . clone ( )
37+ } else {
4038 return None ;
4139 }
42- NodeOrToken :: Token ( it) => it. parent ( ) ?,
40+ } else {
41+ match ctx. covering_element ( ) {
42+ NodeOrToken :: Node ( it) => it,
43+ NodeOrToken :: Token ( it) if it. kind ( ) == COMMENT => {
44+ cov_mark:: hit!( extract_var_in_comment_is_not_applicable) ;
45+ return None ;
46+ }
47+ NodeOrToken :: Token ( it) => it. parent ( ) ?,
48+ }
4349 } ;
50+
4451 let node = node. ancestors ( ) . take_while ( |anc| anc. text_range ( ) == node. text_range ( ) ) . last ( ) ?;
52+ let range = node. text_range ( ) ;
53+
4554 let to_extract = node
4655 . descendants ( )
47- . take_while ( |it| ctx . selection_trimmed ( ) . contains_range ( it. text_range ( ) ) )
56+ . take_while ( |it| range . contains_range ( it. text_range ( ) ) )
4857 . find_map ( valid_target_expr) ?;
4958
5059 let ty = ctx. sema . type_of_expr ( & to_extract) . map ( TypeInfo :: adjusted) ;
@@ -235,6 +244,112 @@ mod tests {
235244
236245 use super :: * ;
237246
247+ #[ test]
248+ fn test_extract_var_simple_without_select ( ) {
249+ check_assist (
250+ extract_variable,
251+ r#"
252+ fn main() -> i32 {
253+ if true {
254+ 1
255+ } else {
256+ 2
257+ }$0
258+ }
259+ "# ,
260+ r#"
261+ fn main() -> i32 {
262+ let $0var_name = if true {
263+ 1
264+ } else {
265+ 2
266+ };
267+ var_name
268+ }
269+ "# ,
270+ ) ;
271+
272+ check_assist (
273+ extract_variable,
274+ r#"
275+ fn foo() -> i32 { 1 }
276+ fn main() {
277+ foo();$0
278+ }
279+ "# ,
280+ r#"
281+ fn foo() -> i32 { 1 }
282+ fn main() {
283+ let $0foo = foo();
284+ }
285+ "# ,
286+ ) ;
287+
288+ check_assist (
289+ extract_variable,
290+ r#"
291+ fn main() {
292+ let a = Some(2);
293+ a.is_some();$0
294+ }
295+ "# ,
296+ r#"
297+ fn main() {
298+ let a = Some(2);
299+ let $0is_some = a.is_some();
300+ }
301+ "# ,
302+ ) ;
303+
304+ check_assist (
305+ extract_variable,
306+ r#"
307+ fn main() {
308+ "hello"$0;
309+ }
310+ "# ,
311+ r#"
312+ fn main() {
313+ let $0var_name = "hello";
314+ }
315+ "# ,
316+ ) ;
317+
318+ check_assist (
319+ extract_variable,
320+ r#"
321+ fn main() {
322+ 1 + 2$0;
323+ }
324+ "# ,
325+ r#"
326+ fn main() {
327+ let $0var_name = 1 + 2;
328+ }
329+ "# ,
330+ ) ;
331+
332+ check_assist (
333+ extract_variable,
334+ r#"
335+ fn main() {
336+ match () {
337+ () if true => 1,
338+ _ => 2,
339+ };$0
340+ }
341+ "# ,
342+ r#"
343+ fn main() {
344+ let $0var_name = match () {
345+ () if true => 1,
346+ _ => 2,
347+ };
348+ }
349+ "# ,
350+ ) ;
351+ }
352+
238353 #[ test]
239354 fn test_extract_var_simple ( ) {
240355 check_assist (
0 commit comments