1
1
use either:: Either ;
2
2
use ide_db:: defs:: { Definition , NameRefClass } ;
3
3
use syntax:: {
4
- ast:: { self , make, HasArgList , HasGenericArgs } ,
5
- ted, AstNode ,
4
+ ast:: { self , make, syntax_factory:: SyntaxFactory , HasArgList , HasGenericArgs } ,
5
+ syntax_editor:: Position ,
6
+ AstNode ,
6
7
} ;
7
8
8
9
use crate :: {
@@ -91,20 +92,34 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
91
92
AssistId ( "add_type_ascription" , AssistKind :: RefactorRewrite ) ,
92
93
"Add `: _` before assignment operator" ,
93
94
ident. text_range ( ) ,
94
- |edit | {
95
- let let_stmt = edit . make_mut ( let_stmt) ;
95
+ |builder | {
96
+ let mut editor = builder . make_editor ( let_stmt. syntax ( ) ) ;
96
97
97
98
if let_stmt. semicolon_token ( ) . is_none ( ) {
98
- ted:: append_child ( let_stmt. syntax ( ) , make:: tokens:: semicolon ( ) ) ;
99
+ editor. insert (
100
+ Position :: last_child_of ( let_stmt. syntax ( ) ) ,
101
+ make:: tokens:: semicolon ( ) ,
102
+ ) ;
99
103
}
100
104
101
105
let placeholder_ty = make:: ty_placeholder ( ) . clone_for_update ( ) ;
102
106
103
- let_stmt. set_ty ( Some ( placeholder_ty. clone ( ) ) ) ;
104
-
105
- if let Some ( cap) = ctx. config . snippet_cap {
106
- edit. add_placeholder_snippet ( cap, placeholder_ty) ;
107
+ if let Some ( pat) = let_stmt. pat ( ) {
108
+ let elements = vec ! [
109
+ make:: token( syntax:: SyntaxKind :: COLON ) . into( ) ,
110
+ make:: token( syntax:: SyntaxKind :: WHITESPACE ) . into( ) ,
111
+ placeholder_ty. syntax( ) . clone( ) . into( ) ,
112
+ ] ;
113
+ editor. insert_all ( Position :: after ( pat. syntax ( ) ) , elements) ;
114
+ if let Some ( cap) = ctx. config . snippet_cap {
115
+ editor. add_annotation (
116
+ placeholder_ty. syntax ( ) ,
117
+ builder. make_placeholder_snippet ( cap) ,
118
+ ) ;
119
+ }
107
120
}
121
+
122
+ builder. add_file_edits ( ctx. file_id ( ) , editor) ;
108
123
} ,
109
124
) ?
110
125
} else {
@@ -123,38 +138,58 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
123
138
AssistId ( "add_turbo_fish" , AssistKind :: RefactorRewrite ) ,
124
139
"Add `::<>`" ,
125
140
ident. text_range ( ) ,
126
- |edit| {
127
- edit. trigger_parameter_hints ( ) ;
141
+ |builder| {
142
+ builder. trigger_parameter_hints ( ) ;
143
+
144
+ let make = SyntaxFactory :: new ( ) ;
145
+ let mut editor = match & turbofish_target {
146
+ Either :: Left ( it) => builder. make_editor ( it. syntax ( ) ) ,
147
+ Either :: Right ( it) => builder. make_editor ( it. syntax ( ) ) ,
148
+ } ;
149
+
150
+ let fish_head = get_fish_head ( & make, number_of_arguments) ;
128
151
129
- let new_arg_list = match turbofish_target {
152
+ match turbofish_target {
130
153
Either :: Left ( path_segment) => {
131
- edit. make_mut ( path_segment) . get_or_create_generic_arg_list ( )
154
+ if let Some ( generic_arg_list) = path_segment. generic_arg_list ( ) {
155
+ editor. replace ( generic_arg_list. syntax ( ) , fish_head. syntax ( ) ) ;
156
+ } else {
157
+ editor. insert (
158
+ Position :: last_child_of ( path_segment. syntax ( ) ) ,
159
+ fish_head. syntax ( ) ,
160
+ ) ;
161
+ }
132
162
}
133
163
Either :: Right ( method_call) => {
134
- edit. make_mut ( method_call) . get_or_create_generic_arg_list ( )
164
+ if let Some ( generic_arg_list) = method_call. generic_arg_list ( ) {
165
+ editor. replace ( generic_arg_list. syntax ( ) , fish_head. syntax ( ) ) ;
166
+ } else {
167
+ let position = if let Some ( arg_list) = method_call. arg_list ( ) {
168
+ Position :: before ( arg_list. syntax ( ) )
169
+ } else {
170
+ Position :: last_child_of ( method_call. syntax ( ) )
171
+ } ;
172
+ editor. insert ( position, fish_head. syntax ( ) ) ;
173
+ }
135
174
}
136
175
} ;
137
176
138
- let fish_head = get_fish_head ( number_of_arguments) . clone_for_update ( ) ;
139
-
140
- // Note: we need to replace the `new_arg_list` instead of being able to use something like
141
- // `GenericArgList::add_generic_arg` as `PathSegment::get_or_create_generic_arg_list`
142
- // always creates a non-turbofish form generic arg list.
143
- ted:: replace ( new_arg_list. syntax ( ) , fish_head. syntax ( ) ) ;
144
-
145
177
if let Some ( cap) = ctx. config . snippet_cap {
146
178
for arg in fish_head. generic_args ( ) {
147
- edit . add_placeholder_snippet ( cap , arg )
179
+ editor . add_annotation ( arg . syntax ( ) , builder . make_placeholder_snippet ( cap ) ) ;
148
180
}
149
181
}
182
+
183
+ editor. add_mappings ( make. finish_with_mappings ( ) ) ;
184
+ builder. add_file_edits ( ctx. file_id ( ) , editor) ;
150
185
} ,
151
186
)
152
187
}
153
188
154
189
/// This will create a turbofish generic arg list corresponding to the number of arguments
155
- fn get_fish_head ( number_of_arguments : usize ) -> ast:: GenericArgList {
190
+ fn get_fish_head ( make : & SyntaxFactory , number_of_arguments : usize ) -> ast:: GenericArgList {
156
191
let args = ( 0 ..number_of_arguments) . map ( |_| make:: type_arg ( make:: ty_placeholder ( ) ) . into ( ) ) ;
157
- make:: turbofish_generic_arg_list ( args)
192
+ make. turbofish_generic_arg_list ( args)
158
193
}
159
194
160
195
#[ cfg( test) ]
0 commit comments