Skip to content

Commit 029ebe2

Browse files
authored
Add support for -spec attribute completion (#1541)
1 parent 527c0c8 commit 029ebe2

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

apps/els_lsp/src/els_completion_provider.erl

+45-6
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,9 @@ find_completions(
195195
find_completions(
196196
_Prefix,
197197
?COMPLETION_TRIGGER_KIND_CHARACTER,
198-
#{trigger := <<"-">>, document := Document, column := 1}
198+
#{trigger := <<"-">>, document := Document, column := 1, line := Line}
199199
) ->
200-
attributes(Document);
200+
attributes(Document, Line);
201201
find_completions(
202202
_Prefix,
203203
?COMPLETION_TRIGGER_KIND_CHARACTER,
@@ -304,7 +304,7 @@ find_completions(
304304
variables(Document);
305305
%% Check for "-anything"
306306
[{atom, _, _}, {'-', _}] ->
307-
attributes(Document);
307+
attributes(Document, Line);
308308
%% Check for "-export(["
309309
[{'[', _}, {'(', _}, {atom, _, export}, {'-', _}] ->
310310
unexported_definitions(Document, function);
@@ -379,6 +379,25 @@ find_completions(
379379
find_completions(_Prefix, _TriggerKind, _Opts) ->
380380
[].
381381

382+
-spec try_to_parse_next_function(binary(), line(), line()) ->
383+
{ok, els_poi:poi()} | error.
384+
try_to_parse_next_function(Text, FromL, ToL) when ToL - FromL < 50 ->
385+
try els_text:range(Text, {FromL, 1}, {ToL, 1}) of
386+
Str ->
387+
{ok, POIs} = els_parser:parse(Str),
388+
case [P || #{kind := function} = P <- POIs] of
389+
[POI | _] ->
390+
{ok, POI};
391+
_ ->
392+
try_to_parse_next_function(Text, FromL, ToL + 1)
393+
end
394+
catch
395+
_:_ ->
396+
error
397+
end;
398+
try_to_parse_next_function(_, _, _) ->
399+
error.
400+
382401
-spec complete_record_field(map(), list()) -> items().
383402
complete_record_field(_Opts, [{atom, _, _}, {'=', _} | _]) ->
384403
[];
@@ -458,8 +477,8 @@ complete_type_definition(Document, Name, ItemFormat) ->
458477
%%=============================================================================
459478
%% Attributes
460479
%%=============================================================================
461-
-spec attributes(els_dt_document:item()) -> items().
462-
attributes(Document) ->
480+
-spec attributes(els_dt_document:item(), line()) -> items().
481+
attributes(Document, Line) ->
463482
[
464483
snippet(attribute_behaviour),
465484
snippet(attribute_callback),
@@ -481,7 +500,7 @@ attributes(Document) ->
481500
snippet(attribute_type),
482501
snippet(attribute_vsn),
483502
attribute_module(Document)
484-
] ++ docs_attributes().
503+
] ++ docs_attributes() ++ attribute_spec(Document, Line).
485504

486505
-spec attribute_module(els_dt_document:item()) -> item().
487506
attribute_module(#{id := Id}) ->
@@ -509,6 +528,26 @@ docs_attributes() ->
509528
[].
510529
-endif.
511530

531+
-spec attribute_spec(Document :: els_dt_document:item(), line()) -> items().
532+
attribute_spec(#{text := Text}, Line) ->
533+
case try_to_parse_next_function(Text, Line + 1, Line + 2) of
534+
{ok, #{id := {Id, Arity}}} ->
535+
Args = [els_arg:new(I, "_") || I <- lists:seq(1, Arity)],
536+
SnippetSupport = snippet_support(),
537+
FunBin = format_function(Id, Args, SnippetSupport, spec),
538+
RetBin =
539+
case SnippetSupport of
540+
false ->
541+
<<" -> _.">>;
542+
true ->
543+
N = integer_to_binary(Arity + 1),
544+
<<" -> ${", N/binary, ":_}.">>
545+
end,
546+
[snippet(<<"-spec">>, <<"spec ", FunBin/binary, RetBin/binary>>)];
547+
error ->
548+
[]
549+
end.
550+
512551
%%=============================================================================
513552
%% Include paths
514553
%%=============================================================================

apps/els_lsp/test/els_completion_SUITE.erl

+6
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,12 @@ attributes(Config) ->
225225
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
226226
kind => ?COMPLETION_ITEM_KIND_SNIPPET,
227227
label => <<"-module(completion_attributes).">>
228+
},
229+
#{
230+
insertText => <<"spec exported_function() -> ${1:_}.">>,
231+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
232+
kind => ?COMPLETION_ITEM_KIND_SNIPPET,
233+
label => <<"-spec">>
228234
}
229235
] ++ docs_attributes(),
230236
#{result := Completions} =

0 commit comments

Comments
 (0)