@@ -44,6 +44,7 @@ trigger_characters() ->
44
44
<<" -" >>,
45
45
<<" \" " >>,
46
46
<<" {" >>,
47
+ <<" /" >>,
47
48
<<" " >>
48
49
].
49
50
@@ -198,6 +199,24 @@ find_completions(
198
199
#{trigger := <<" -" >>, document := Document , column := 1 , line := Line }
199
200
) ->
200
201
attributes (Document , Line );
202
+ find_completions (
203
+ Prefix ,
204
+ ? COMPLETION_TRIGGER_KIND_CHARACTER ,
205
+ #{trigger := <<" /" >>}
206
+ ) ->
207
+ Tokens = lists :reverse (els_text :tokens (Prefix )),
208
+ case in_binary_heuristic (Tokens ) of
209
+ true ->
210
+ binary_type_specifier ();
211
+ false ->
212
+ []
213
+ end ;
214
+ find_completions (
215
+ Prefix ,
216
+ ? COMPLETION_TRIGGER_KIND_CHARACTER ,
217
+ #{trigger := <<" -" >>}
218
+ ) ->
219
+ binary_type_specifiers (Prefix );
201
220
find_completions (
202
221
_Prefix ,
203
222
? COMPLETION_TRIGGER_KIND_CHARACTER ,
@@ -305,6 +324,18 @@ find_completions(
305
324
% % Check for "-anything"
306
325
[{atom , _ , _ }, {'-' , _ }] ->
307
326
attributes (Document , Line );
327
+ % % Check for "[...] -"
328
+ [{'-' , _ } | _ ] ->
329
+ binary_type_specifiers (Prefix );
330
+ % % Check for "[...] -"
331
+ [{'/' , _ } | _ ] ->
332
+ Tokens = lists :reverse (els_text :tokens (Prefix )),
333
+ case in_binary_heuristic (Tokens ) of
334
+ true ->
335
+ binary_type_specifier ();
336
+ false ->
337
+ []
338
+ end ;
308
339
% % Check for "-export(["
309
340
[{'[' , _ }, {'(' , _ }, {atom , _ , export }, {'-' , _ }] ->
310
341
unexported_definitions (Document , function );
@@ -392,6 +423,115 @@ find_completions(
392
423
find_completions (_Prefix , _TriggerKind , _Opts ) ->
393
424
[].
394
425
426
+ -spec binary_type_specifiers (binary ()) -> [completion_item ()].
427
+ binary_type_specifiers (Prefix ) ->
428
+ % % in_binary_heuristic will only consider current line
429
+ % % TODO: make it work for multi-line binaries too.
430
+ Tokens = lists :reverse (els_text :tokens (Prefix )),
431
+ case
432
+ in_binary_heuristic (Tokens ) andalso
433
+ in_binary_type_specifier (Tokens , [])
434
+ of
435
+ {true , TypeListTokens } ->
436
+ HasType = lists :any (
437
+ fun (T ) ->
438
+ lists :member (T , binary_types ())
439
+ end ,
440
+ TypeListTokens
441
+ ),
442
+ HasEndianess = lists :any (
443
+ fun (T ) ->
444
+ lists :member (T , binary_endianness ())
445
+ end ,
446
+ TypeListTokens
447
+ ),
448
+ HasSignedness = lists :any (
449
+ fun (T ) ->
450
+ lists :member (T , binary_signedness ())
451
+ end ,
452
+ TypeListTokens
453
+ ),
454
+ HasUnit = lists :member (unit , TypeListTokens ),
455
+ [binary_type_specifier (unit ) || not HasUnit ] ++
456
+ [binary_type_specifier (Label ) || Label <- binary_types (), not HasType ] ++
457
+ [binary_type_specifier (Label ) || Label <- binary_endianness (), not HasEndianess ] ++
458
+ [binary_type_specifier (Label ) || Label <- binary_signedness (), not HasSignedness ];
459
+ false ->
460
+ []
461
+ end .
462
+
463
+ -spec in_binary_heuristic ([any ()]) -> boolean ().
464
+ in_binary_heuristic ([{'>>' , _ } | _ ]) ->
465
+ false ;
466
+ in_binary_heuristic ([{'<<' , _ } | _ ]) ->
467
+ true ;
468
+ in_binary_heuristic ([_ | T ]) ->
469
+ in_binary_heuristic (T );
470
+ in_binary_heuristic ([]) ->
471
+ false .
472
+
473
+ -spec in_binary_type_specifier ([any ()], [atom ()]) -> {true , [atom ()]} | false .
474
+ in_binary_type_specifier ([{integer , _ , _ }, {':' , _ }, {atom , _ , unit } | T ], Spec ) ->
475
+ in_binary_type_specifier (T , [unit | Spec ]);
476
+ in_binary_type_specifier ([{atom , _ , Atom } | T ], Spec ) ->
477
+ case lists :member (Atom , binary_type_specifiers ()) of
478
+ true ->
479
+ in_binary_type_specifier (T , [Atom | Spec ]);
480
+ false ->
481
+ false
482
+ end ;
483
+ in_binary_type_specifier ([{'-' , _ } | T ], Spec ) ->
484
+ in_binary_type_specifier (T , Spec );
485
+ in_binary_type_specifier ([{'/' , _ } | _ ], Spec ) ->
486
+ {true , Spec };
487
+ in_binary_type_specifier ([], _Spec ) ->
488
+ false .
489
+
490
+ -spec binary_type_specifiers () -> [atom ()].
491
+ binary_type_specifiers () ->
492
+ binary_types () ++ binary_signedness () ++ binary_endianness () ++ [unit ].
493
+
494
+ -spec binary_signedness () -> [atom ()].
495
+ binary_signedness () ->
496
+ [signed , unsigned ].
497
+
498
+ -spec binary_types () -> [atom ()].
499
+ binary_types () ->
500
+ [integer , float , binary , bytes , bitstring , bits , utf8 , utf16 , utf32 ].
501
+
502
+ -spec binary_endianness () -> [atom ()].
503
+ binary_endianness () ->
504
+ [big , little , native ].
505
+
506
+ -spec binary_type_specifier () -> [completion_item ()].
507
+ binary_type_specifier () ->
508
+ Labels = binary_type_specifiers (),
509
+ [binary_type_specifier (Label ) || Label <- Labels ].
510
+
511
+ -spec binary_type_specifier (atom ()) -> completion_item ().
512
+ binary_type_specifier (unit ) ->
513
+ case snippet_support () of
514
+ true ->
515
+ #{
516
+ label => <<" unit:N" >>,
517
+ kind => ? COMPLETION_ITEM_KIND_TYPE_PARAM ,
518
+ insertTextFormat => ? INSERT_TEXT_FORMAT_SNIPPET ,
519
+ insertText => <<" unit:${1:N}" >>
520
+ };
521
+ false ->
522
+ #{
523
+ label => <<" unit:" >>,
524
+ kind => ? COMPLETION_ITEM_KIND_TYPE_PARAM ,
525
+ insertTextFormat => ? INSERT_TEXT_FORMAT_PLAIN_TEXT
526
+ }
527
+ end ;
528
+ binary_type_specifier (Label ) ->
529
+ #{
530
+ label => atom_to_binary (Label ),
531
+ kind => ? COMPLETION_ITEM_KIND_TYPE_PARAM ,
532
+ insertTextFormat => ? INSERT_TEXT_FORMAT_PLAIN_TEXT
533
+ }.
534
+
395
535
-spec complete_record_field (map (), list ()) -> items ().
396
536
complete_record_field (_Opts , [{atom , _ , _ }, {'=' , _ } | _ ]) ->
397
537
[];
0 commit comments