@@ -346,33 +346,49 @@ end_symbol(ExtractString) ->
346
346
non_neg_integer ()
347
347
) -> [string ()].
348
348
get_args (PoiRange , Document , FromL , FunBeginLine ) ->
349
- % % TODO: Possible improvement. To make this bullet proof we should
350
- % % ignore vars defined inside LCs and funs()
351
- VarPOIs = els_poi :sort (els_dt_document :pois (Document , [variable ])),
352
349
BeforeRange = #{from => {FunBeginLine , 1 }, to => {FromL , 1 }},
353
- VarsBefore = ids_in_range (BeforeRange , VarPOIs ),
354
- VarsInside = ids_in_range (PoiRange , VarPOIs ),
350
+ VarPOIsBefore = els_dt_document :pois_in_range (Document , [variable ], BeforeRange ),
351
+ % % Remove all variables inside LCs or keyword expressions
352
+ LCPOIs = els_dt_document :pois (Document , [list_comp ]),
353
+ FunExprPOIs = [
354
+ POI
355
+ || #{id := fun_expr } = POI <- els_dt_document :pois (Document , [keyword_expr ])
356
+ ],
357
+ % % Only consider fun exprs that doesn't contain the selected range
358
+ ExcludePOIs = [
359
+ POI
360
+ || #{range := R } = POI <- FunExprPOIs ++ LCPOIs , not els_range :in (PoiRange , R )
361
+ ],
362
+ VarsBefore = [
363
+ Id
364
+ || #{range := VarRange , id := Id } <- els_poi :sort (VarPOIsBefore ),
365
+ not_in_any_range (VarRange , ExcludePOIs )
366
+ ],
367
+ % % Find all variables defined before the current function that are used
368
+ % % inside the selected range.
369
+ VarPOIsInside = els_dt_document :pois_in_range (Document , [variable ], PoiRange ),
355
370
els_utils :uniq ([
356
371
atom_to_list (Id )
357
- || Id <- VarsInside ,
372
+ || #{ id : = Id } <- VarPOIsInside ,
358
373
lists :member (Id , VarsBefore )
359
374
]).
360
375
361
- -spec ids_in_range (els_poi :poi_range (), [els_poi :poi ()]) -> [atom ()].
362
- ids_in_range (PoiRange , VarPOIs ) ->
363
- [
364
- Id
365
- || #{range := R , id := Id } <- VarPOIs ,
366
- els_range :in (R , PoiRange )
367
- ].
376
+ -spec not_in_any_range (els_poi :poi_range (), [els_poi :poi ()]) -> boolean ().
377
+ not_in_any_range (VarRange , POIs ) ->
378
+ not lists :any (
379
+ fun (#{range := Range }) ->
380
+ els_range :in (VarRange , Range )
381
+ end ,
382
+ POIs
383
+ ).
368
384
369
385
-spec extract_range (els_dt_document :item (), range ()) -> els_poi :poi_range ().
370
386
extract_range (#{text := Text } = Document , Range ) ->
371
387
PoiRange = els_range :to_poi_range (Range ),
372
388
#{from := {CurrL , CurrC } = From , to := To } = PoiRange ,
373
389
POIs = els_dt_document :get_element_at_pos (Document , CurrL , CurrC ),
374
390
MarkedText = els_text :range (Text , From , To ),
375
- case is_keyword_expr (MarkedText ) of
391
+ case els_text : is_keyword_expr (MarkedText ) of
376
392
true ->
377
393
case sort_by_range_size ([P || #{kind := keyword_expr } = P <- POIs ]) of
378
394
[] ->
@@ -384,18 +400,6 @@ extract_range(#{text := Text} = Document, Range) ->
384
400
PoiRange
385
401
end .
386
402
387
- -spec is_keyword_expr (binary ()) -> boolean ().
388
- is_keyword_expr (Text ) ->
389
- lists :member (Text , [
390
- <<" begin" >>,
391
- <<" case" >>,
392
- <<" fun" >>,
393
- <<" if" >>,
394
- <<" maybe" >>,
395
- <<" receive" >>,
396
- <<" try" >>
397
- ]).
398
-
399
403
-spec sort_by_range_size (_ ) -> _ .
400
404
sort_by_range_size (POIs ) ->
401
405
lists :sort ([{range_size (P ), P } || P <- POIs ]).
0 commit comments