@@ -5,7 +5,7 @@ use ide_db::{
5
5
EditionedFileId , RootDatabase ,
6
6
} ;
7
7
use syntax:: {
8
- ast:: { self , AstNode , AstToken , HasName } ,
8
+ ast:: { self , syntax_factory :: SyntaxFactory , AstNode , AstToken , HasName } ,
9
9
SyntaxElement , TextRange ,
10
10
} ;
11
11
@@ -43,22 +43,6 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
43
43
} ?;
44
44
let initializer_expr = let_stmt. initializer ( ) ?;
45
45
46
- let delete_range = delete_let. then ( || {
47
- if let Some ( whitespace) = let_stmt
48
- . syntax ( )
49
- . next_sibling_or_token ( )
50
- . and_then ( SyntaxElement :: into_token)
51
- . and_then ( ast:: Whitespace :: cast)
52
- {
53
- TextRange :: new (
54
- let_stmt. syntax ( ) . text_range ( ) . start ( ) ,
55
- whitespace. syntax ( ) . text_range ( ) . end ( ) ,
56
- )
57
- } else {
58
- let_stmt. syntax ( ) . text_range ( )
59
- }
60
- } ) ;
61
-
62
46
let wrap_in_parens = references
63
47
. into_iter ( )
64
48
. filter_map ( |FileReference { range, name, .. } | match name {
@@ -73,40 +57,60 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
73
57
}
74
58
let usage_node =
75
59
name_ref. syntax ( ) . ancestors ( ) . find ( |it| ast:: PathExpr :: can_cast ( it. kind ( ) ) ) ;
76
- let usage_parent_option = usage_node. and_then ( |it| it. parent ( ) ) ;
60
+ let usage_parent_option = usage_node. as_ref ( ) . and_then ( |it| it. parent ( ) ) ;
77
61
let usage_parent = match usage_parent_option {
78
62
Some ( u) => u,
79
- None => return Some ( ( range , name_ref, false ) ) ,
63
+ None => return Some ( ( name_ref, false ) ) ,
80
64
} ;
81
- Some ( ( range, name_ref, initializer_expr. needs_parens_in ( & usage_parent) ) )
65
+ let should_wrap = initializer_expr
66
+ . needs_parens_in_place_of ( & usage_parent, usage_node. as_ref ( ) . unwrap ( ) ) ;
67
+ Some ( ( name_ref, should_wrap) )
82
68
} )
83
69
. collect :: < Option < Vec < _ > > > ( ) ?;
84
70
85
- let init_str = initializer_expr. syntax ( ) . text ( ) . to_string ( ) ;
86
- let init_in_paren = format ! ( "({init_str})" ) ;
87
-
88
71
let target = match target {
89
- ast:: NameOrNameRef :: Name ( it) => it. syntax ( ) . text_range ( ) ,
90
- ast:: NameOrNameRef :: NameRef ( it) => it. syntax ( ) . text_range ( ) ,
72
+ ast:: NameOrNameRef :: Name ( it) => it. syntax ( ) . clone ( ) ,
73
+ ast:: NameOrNameRef :: NameRef ( it) => it. syntax ( ) . clone ( ) ,
91
74
} ;
92
75
93
76
acc. add (
94
77
AssistId ( "inline_local_variable" , AssistKind :: RefactorInline ) ,
95
78
"Inline variable" ,
96
- target,
79
+ target. text_range ( ) ,
97
80
move |builder| {
98
- if let Some ( range) = delete_range {
99
- builder. delete ( range) ;
81
+ let mut editor = builder. make_editor ( & target) ;
82
+ if delete_let {
83
+ editor. delete ( let_stmt. syntax ( ) ) ;
84
+ if let Some ( whitespace) = let_stmt
85
+ . syntax ( )
86
+ . next_sibling_or_token ( )
87
+ . and_then ( SyntaxElement :: into_token)
88
+ . and_then ( ast:: Whitespace :: cast)
89
+ {
90
+ editor. delete ( whitespace. syntax ( ) ) ;
91
+ }
100
92
}
101
- for ( range, name, should_wrap) in wrap_in_parens {
102
- let replacement = if should_wrap { & init_in_paren } else { & init_str } ;
103
- if ast:: RecordExprField :: for_field_name ( & name) . is_some ( ) {
93
+
94
+ let make = SyntaxFactory :: new ( ) ;
95
+
96
+ for ( name, should_wrap) in wrap_in_parens {
97
+ let replacement = if should_wrap {
98
+ make. expr_paren ( initializer_expr. clone ( ) ) . into ( )
99
+ } else {
100
+ initializer_expr. clone ( )
101
+ } ;
102
+
103
+ if let Some ( record_field) = ast:: RecordExprField :: for_field_name ( & name) {
104
104
cov_mark:: hit!( inline_field_shorthand) ;
105
- builder. insert ( range. end ( ) , format ! ( ": {replacement}" ) ) ;
105
+ let replacement = make. record_expr_field ( name, Some ( replacement) ) ;
106
+ editor. replace ( record_field. syntax ( ) , replacement. syntax ( ) ) ;
106
107
} else {
107
- builder . replace ( range , replacement. clone ( ) )
108
+ editor . replace ( name . syntax ( ) , replacement. syntax ( ) ) ;
108
109
}
109
110
}
111
+
112
+ editor. add_mappings ( make. finish_with_mappings ( ) ) ;
113
+ builder. add_file_edits ( ctx. file_id ( ) , editor) ;
110
114
} ,
111
115
)
112
116
}
@@ -939,6 +943,54 @@ fn main() {
939
943
fn main() {
940
944
let _ = (|| 2)();
941
945
}
946
+ "# ,
947
+ ) ;
948
+ }
949
+
950
+ #[ test]
951
+ fn test_wrap_in_parens ( ) {
952
+ check_assist (
953
+ inline_local_variable,
954
+ r#"
955
+ fn main() {
956
+ let $0a = 123 < 456;
957
+ let b = !a;
958
+ }
959
+ "# ,
960
+ r#"
961
+ fn main() {
962
+ let b = !(123 < 456);
963
+ }
964
+ "# ,
965
+ ) ;
966
+ check_assist (
967
+ inline_local_variable,
968
+ r#"
969
+ trait Foo {
970
+ fn foo(&self);
971
+ }
972
+
973
+ impl Foo for bool {
974
+ fn foo(&self) {}
975
+ }
976
+
977
+ fn main() {
978
+ let $0a = 123 < 456;
979
+ let b = a.foo();
980
+ }
981
+ "# ,
982
+ r#"
983
+ trait Foo {
984
+ fn foo(&self);
985
+ }
986
+
987
+ impl Foo for bool {
988
+ fn foo(&self) {}
989
+ }
990
+
991
+ fn main() {
992
+ let b = (123 < 456).foo();
993
+ }
942
994
"# ,
943
995
) ;
944
996
}
0 commit comments