@@ -25,7 +25,8 @@ options() ->
25
25
<<" suggest-spec" >>,
26
26
<<" function-references" >>,
27
27
<<" refactor.extract" >>,
28
- <<" add-behaviour-callbacks" >>
28
+ <<" add-behaviour-callbacks" >>,
29
+ <<" bump-variables" >>
29
30
],
30
31
#{
31
32
commands => [
@@ -115,6 +116,15 @@ execute_command(<<"refactor.extract">>, [
115
116
]) ->
116
117
ok = extract_function (Uri , Range ),
117
118
[];
119
+ execute_command (<<" bump-variables" >>, [
120
+ #{
121
+ <<" uri" >> := Uri ,
122
+ <<" range" >> := Range ,
123
+ <<" name" >> := Name
124
+ }
125
+ ]) ->
126
+ ok = bump_variables (Uri , Range , Name ),
127
+ [];
118
128
execute_command (<<" add-behaviour-callbacks" >>, [
119
129
#{
120
130
<<" uri" >> := Uri ,
@@ -206,6 +216,63 @@ execute_command(Command, Arguments) ->
206
216
end ,
207
217
[].
208
218
219
+ -spec bump_variables (uri (), range (), binary ()) -> ok .
220
+ bump_variables (Uri , Range , VarName ) ->
221
+ {Name , Number } = split_variable (VarName ),
222
+ {ok , Document } = els_utils :lookup_document (Uri ),
223
+ VarPOIs = els_poi :sort (els_dt_document :pois (Document , [variable ])),
224
+ VarRange = els_range :to_poi_range (Range ),
225
+ ScopeRange = els_scope :variable_scope_range (VarRange , Document ),
226
+ Changes =
227
+ [
228
+ bump_variable_change (POI )
229
+ || POI <- pois_in (VarPOIs , ScopeRange ),
230
+ should_bump_variable (POI , Name , Number )
231
+ ],
232
+ Method = <<" workspace/applyEdit" >>,
233
+ Params = #{edit => #{changes => #{Uri => Changes }}},
234
+ els_server :send_request (Method , Params ).
235
+
236
+ -spec should_bump_variable (els_poi :poi (), binary (), binary ()) -> boolean ().
237
+ should_bump_variable (#{id := Id }, Name , Number ) ->
238
+ case split_variable (Id ) of
239
+ {PName , PNumber } when PName == Name ->
240
+ binary_to_integer (PNumber ) >= binary_to_integer (Number );
241
+ _ ->
242
+ false
243
+ end .
244
+
245
+ -spec bump_variable_change (els_poi :poi ()) -> map ().
246
+ bump_variable_change (#{id := Id , range := PoiRange }) ->
247
+ {Name , Number } = split_variable (Id ),
248
+ NewNumber = integer_to_binary (binary_to_integer (Number ) + 1 ),
249
+ NewId = binary_to_atom (<<Name /binary , NewNumber /binary >>, utf8 ),
250
+ #{
251
+ newText => NewId ,
252
+ range => els_protocol :range (PoiRange )
253
+ }.
254
+
255
+ -spec pois_in ([els_poi :poi ()], els_poi :poi_range ()) ->
256
+ [els_poi :poi ()].
257
+ pois_in (POIs , Range ) ->
258
+ [POI || #{range := R } = POI <- POIs , els_range :in (R , Range )].
259
+
260
+ -spec split_variable (atom ()) -> {binary (), binary ()}.
261
+ split_variable (Name ) when is_atom (Name ) ->
262
+ split_variable (atom_to_list (Name ));
263
+ split_variable (Name ) when is_binary (Name ) ->
264
+ split_variable (unicode :characters_to_list (Name ));
265
+ split_variable (Name ) when is_list (Name ) ->
266
+ split_variable (lists :reverse (Name ), []).
267
+
268
+ -spec split_variable (string (), string ()) -> {binary (), binary ()} | error .
269
+ split_variable ([H | T ], Acc ) when $0 =< H , H =< $9 ->
270
+ split_variable (T , [H | Acc ]);
271
+ split_variable (_Name , []) ->
272
+ error ;
273
+ split_variable (Name , Acc ) ->
274
+ {list_to_binary (lists :reverse (Name )), list_to_binary (Acc )}.
275
+
209
276
-spec extract_function (uri (), range ()) -> ok .
210
277
extract_function (Uri , Range ) ->
211
278
{ok , [#{text := Text } = Document ]} = els_dt_document :lookup (Uri ),
0 commit comments