@@ -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 ,
@@ -308,6 +327,18 @@ find_completions(
308
327
% % Check for "-anything"
309
328
[{atom , _ , _ }, {'-' , _ }] ->
310
329
attributes (Document , Line );
330
+ % % Check for "[...] -"
331
+ [{'-' , _ } | _ ] ->
332
+ binary_type_specifiers (Prefix );
333
+ % % Check for "[...] -"
334
+ [{'/' , _ } | _ ] ->
335
+ Tokens = lists :reverse (els_text :tokens (Prefix )),
336
+ case in_binary_heuristic (Tokens ) of
337
+ true ->
338
+ binary_type_specifier ();
339
+ false ->
340
+ []
341
+ end ;
311
342
% % Check for "-export(["
312
343
[{'[' , _ }, {'(' , _ }, {atom , _ , export }, {'-' , _ }] ->
313
344
unexported_definitions (Document , function );
@@ -476,6 +507,115 @@ complete_atom(Name, Tokens, Opts) ->
476
507
end
477
508
end .
478
509
510
+ -spec binary_type_specifiers (binary ()) -> [completion_item ()].
511
+ binary_type_specifiers (Prefix ) ->
512
+ % % in_binary_heuristic will only consider current line
513
+ % % TODO: make it work for multi-line binaries too.
514
+ Tokens = lists :reverse (els_text :tokens (Prefix )),
515
+ case
516
+ in_binary_heuristic (Tokens ) andalso
517
+ in_binary_type_specifier (Tokens , [])
518
+ of
519
+ {true , TypeListTokens } ->
520
+ HasType = lists :any (
521
+ fun (T ) ->
522
+ lists :member (T , binary_types ())
523
+ end ,
524
+ TypeListTokens
525
+ ),
526
+ HasEndianess = lists :any (
527
+ fun (T ) ->
528
+ lists :member (T , binary_endianness ())
529
+ end ,
530
+ TypeListTokens
531
+ ),
532
+ HasSignedness = lists :any (
533
+ fun (T ) ->
534
+ lists :member (T , binary_signedness ())
535
+ end ,
536
+ TypeListTokens
537
+ ),
538
+ HasUnit = lists :member (unit , TypeListTokens ),
539
+ [binary_type_specifier (unit ) || not HasUnit ] ++
540
+ [binary_type_specifier (Label ) || Label <- binary_types (), not HasType ] ++
541
+ [binary_type_specifier (Label ) || Label <- binary_endianness (), not HasEndianess ] ++
542
+ [binary_type_specifier (Label ) || Label <- binary_signedness (), not HasSignedness ];
543
+ false ->
544
+ []
545
+ end .
546
+
547
+ -spec in_binary_heuristic ([any ()]) -> boolean ().
548
+ in_binary_heuristic ([{'>>' , _ } | _ ]) ->
549
+ false ;
550
+ in_binary_heuristic ([{'<<' , _ } | _ ]) ->
551
+ true ;
552
+ in_binary_heuristic ([_ | T ]) ->
553
+ in_binary_heuristic (T );
554
+ in_binary_heuristic ([]) ->
555
+ false .
556
+
557
+ -spec in_binary_type_specifier ([any ()], [atom ()]) -> {true , [atom ()]} | false .
558
+ in_binary_type_specifier ([{integer , _ , _ }, {':' , _ }, {atom , _ , unit } | T ], Spec ) ->
559
+ in_binary_type_specifier (T , [unit | Spec ]);
560
+ in_binary_type_specifier ([{atom , _ , Atom } | T ], Spec ) ->
561
+ case lists :member (Atom , binary_type_specifiers ()) of
562
+ true ->
563
+ in_binary_type_specifier (T , [Atom | Spec ]);
564
+ false ->
565
+ false
566
+ end ;
567
+ in_binary_type_specifier ([{'-' , _ } | T ], Spec ) ->
568
+ in_binary_type_specifier (T , Spec );
569
+ in_binary_type_specifier ([{'/' , _ } | _ ], Spec ) ->
570
+ {true , Spec };
571
+ in_binary_type_specifier ([], _Spec ) ->
572
+ false .
573
+
574
+ -spec binary_type_specifiers () -> [atom ()].
575
+ binary_type_specifiers () ->
576
+ binary_types () ++ binary_signedness () ++ binary_endianness () ++ [unit ].
577
+
578
+ -spec binary_signedness () -> [atom ()].
579
+ binary_signedness () ->
580
+ [signed , unsigned ].
581
+
582
+ -spec binary_types () -> [atom ()].
583
+ binary_types () ->
584
+ [integer , float , binary , bytes , bitstring , bits , utf8 , utf16 , utf32 ].
585
+
586
+ -spec binary_endianness () -> [atom ()].
587
+ binary_endianness () ->
588
+ [big , little , native ].
589
+
590
+ -spec binary_type_specifier () -> [completion_item ()].
591
+ binary_type_specifier () ->
592
+ Labels = binary_type_specifiers (),
593
+ [binary_type_specifier (Label ) || Label <- Labels ].
594
+
595
+ -spec binary_type_specifier (atom ()) -> completion_item ().
596
+ binary_type_specifier (unit ) ->
597
+ case snippet_support () of
598
+ true ->
599
+ #{
600
+ label => <<" unit:N" >>,
601
+ kind => ? COMPLETION_ITEM_KIND_TYPE_PARAM ,
602
+ insertTextFormat => ? INSERT_TEXT_FORMAT_SNIPPET ,
603
+ insertText => <<" unit:${1:N}" >>
604
+ };
605
+ false ->
606
+ #{
607
+ label => <<" unit:" >>,
608
+ kind => ? COMPLETION_ITEM_KIND_TYPE_PARAM ,
609
+ insertTextFormat => ? INSERT_TEXT_FORMAT_PLAIN_TEXT
610
+ }
611
+ end ;
612
+ binary_type_specifier (Label ) ->
613
+ #{
614
+ label => atom_to_binary (Label ),
615
+ kind => ? COMPLETION_ITEM_KIND_TYPE_PARAM ,
616
+ insertTextFormat => ? INSERT_TEXT_FORMAT_PLAIN_TEXT
617
+ }.
618
+
479
619
-spec complete_record_field (map (), list ()) -> items ().
480
620
complete_record_field (_Opts , [{atom , _ , _ }, {'=' , _ } | _ ]) ->
481
621
[];
0 commit comments