Skip to content

Commit 0189da5

Browse files
committed
Add better support for completing keywords
1 parent 6410bf6 commit 0189da5

File tree

1 file changed

+164
-27
lines changed

1 file changed

+164
-27
lines changed

apps/els_lsp/src/els_completion_provider.erl

+164-27
Original file line numberDiff line numberDiff line change
@@ -349,25 +349,14 @@ find_completions(
349349
complete_type_definition(Document, Name, ItemFormat);
350350
%% Check for "[...] atom"
351351
[{atom, _, Name} | _] = Tokens ->
352-
NameBinary = atom_to_binary(Name, utf8),
353-
{ItemFormat, POIKind} = completion_context(Document, Line, Column, Tokens),
354-
case ItemFormat of
355-
arity_only ->
356-
%% Only complete unexported definitions when in export
357-
unexported_definitions(Document, POIKind);
358-
_ ->
359-
case complete_record_field(Opts, Tokens) of
360-
[] ->
361-
keywords(POIKind, ItemFormat) ++
362-
bifs(POIKind, ItemFormat) ++
363-
atoms(Document, NameBinary) ++
364-
all_record_fields(Document, NameBinary) ++
365-
modules(NameBinary) ++
366-
definitions(Document, POIKind, ItemFormat) ++
367-
snippets(POIKind, ItemFormat);
368-
RecordFields ->
369-
RecordFields
370-
end
352+
complete_atom(Name, Tokens, Opts);
353+
%% Treat keywords as atom completion
354+
[{Name, _} | _] = Tokens ->
355+
case lists:member(Name, keywords()) of
356+
true ->
357+
complete_atom(Name, Tokens, Opts);
358+
false ->
359+
[]
371360
end;
372361
Tokens ->
373362
?LOG_DEBUG(
@@ -379,6 +368,31 @@ find_completions(
379368
find_completions(_Prefix, _TriggerKind, _Opts) ->
380369
[].
381370

371+
372+
-spec complete_atom(atom(), [any()], map()) -> [completion_item()].
373+
complete_atom(Name, Tokens, Opts) ->
374+
#{document := Document, line := Line, column := Column} = Opts,
375+
NameBinary = atom_to_binary(Name, utf8),
376+
{ItemFormat, POIKind} = completion_context(Document, Line, Column, Tokens),
377+
case ItemFormat of
378+
arity_only ->
379+
%% Only complete unexported definitions when in export
380+
unexported_definitions(Document, POIKind);
381+
_ ->
382+
case complete_record_field(Opts, Tokens) of
383+
[] ->
384+
keywords(POIKind, ItemFormat) ++
385+
bifs(POIKind, ItemFormat) ++
386+
atoms(Document, NameBinary) ++
387+
all_record_fields(Document, NameBinary) ++
388+
modules(NameBinary) ++
389+
definitions(Document, POIKind, ItemFormat) ++
390+
snippets(POIKind, ItemFormat);
391+
RecordFields ->
392+
RecordFields
393+
end
394+
end.
395+
382396
-spec try_to_parse_next_function(binary(), line(), line()) ->
383397
{ok, els_poi:poi()} | error.
384398
try_to_parse_next_function(Text, FromL, ToL) when ToL - FromL < 50 ->
@@ -992,7 +1006,15 @@ keywords(type_definition, _ItemFormat) ->
9921006
keywords(_POIKind, arity_only) ->
9931007
[];
9941008
keywords(_POIKind, _ItemFormat) ->
995-
Keywords = [
1009+
Keywords = keywords(),
1010+
[
1011+
keyword_completion_item(K, snippet_support())
1012+
|| K <- Keywords
1013+
].
1014+
1015+
-spec keywords() -> [atom()].
1016+
keywords() ->
1017+
[
9961018
'after',
9971019
'and',
9981020
'andalso',
@@ -1008,9 +1030,11 @@ keywords(_POIKind, _ItemFormat) ->
10081030
'cond',
10091031
'div',
10101032
'end',
1033+
'else',
10111034
'fun',
10121035
'if',
10131036
'let',
1037+
'maybe',
10141038
'not',
10151039
'of',
10161040
'or',
@@ -1020,15 +1044,128 @@ keywords(_POIKind, _ItemFormat) ->
10201044
'try',
10211045
'when',
10221046
'xor'
1023-
],
1024-
[
1025-
#{
1026-
label => atom_to_binary(K, utf8),
1027-
kind => ?COMPLETION_ITEM_KIND_KEYWORD
1028-
}
1029-
|| K <- Keywords
10301047
].
10311048

1049+
-spec keyword_completion_item(_, _) -> _.
1050+
keyword_completion_item('case', true) ->
1051+
#{
1052+
label => <<"case">>,
1053+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1054+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1055+
insertText =>
1056+
<<
1057+
"case ${1:Exprs} of\n"
1058+
" ${2:Pattern} ->\n"
1059+
" ${3:Body}\n"
1060+
"end"
1061+
>>
1062+
};
1063+
keyword_completion_item('try', true) ->
1064+
#{
1065+
label => <<"try">>,
1066+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1067+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1068+
insertText =>
1069+
<<
1070+
"try ${1:Exprs}\n"
1071+
"catch\n"
1072+
" ${2:Class}:${3:ExceptionPattern}:${4:Stacktrace} ->\n"
1073+
" ${5:ExceptionBody}\n"
1074+
"end"
1075+
>>
1076+
};
1077+
keyword_completion_item('catch', true) ->
1078+
#{
1079+
label => <<"catch">>,
1080+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1081+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1082+
insertText =>
1083+
<<
1084+
"catch\n"
1085+
" ${1:Class}:${2:ExceptionPattern}:${3:Stacktrace} ->\n"
1086+
" ${4:ExceptionBody}\n"
1087+
"end"
1088+
>>
1089+
};
1090+
keyword_completion_item('begin', true) ->
1091+
#{
1092+
label => <<"begin">>,
1093+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1094+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1095+
insertText =>
1096+
<<
1097+
"begin\n"
1098+
" ${1:Body}\n"
1099+
"end"
1100+
>>
1101+
};
1102+
keyword_completion_item('maybe', true) ->
1103+
#{
1104+
label => <<"maybe">>,
1105+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1106+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1107+
insertText =>
1108+
<<
1109+
"maybe\n"
1110+
" ${1:Body}\n"
1111+
"end"
1112+
>>
1113+
};
1114+
keyword_completion_item('after', true) ->
1115+
#{
1116+
label => <<"after">>,
1117+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1118+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1119+
insertText =>
1120+
<<
1121+
"after\n"
1122+
" ${1:Duration} ->\n"
1123+
" ${2:Body}"
1124+
>>
1125+
};
1126+
keyword_completion_item('else', true) ->
1127+
#{
1128+
label => <<"else">>,
1129+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1130+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1131+
insertText =>
1132+
<<
1133+
"else\n"
1134+
" ${1:Pattern} ->\n"
1135+
" ${2:Body}"
1136+
>>
1137+
};
1138+
keyword_completion_item('of', true) ->
1139+
#{
1140+
label => <<"of">>,
1141+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1142+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1143+
insertText =>
1144+
<<
1145+
"of\n"
1146+
" ${1:Pattern} ->\n"
1147+
" ${2:Body}"
1148+
>>
1149+
};
1150+
keyword_completion_item('receive', true) ->
1151+
#{
1152+
label => <<"receive">>,
1153+
kind => ?COMPLETION_ITEM_KIND_KEYWORD,
1154+
insertTextFormat => ?INSERT_TEXT_FORMAT_SNIPPET,
1155+
insertText =>
1156+
<<
1157+
"receive\n"
1158+
" ${1:Pattern} ->\n"
1159+
" ${2:Body}\n"
1160+
"end"
1161+
>>
1162+
};
1163+
keyword_completion_item(K, _SnippetSupport) ->
1164+
#{
1165+
label => atom_to_binary(K, utf8),
1166+
kind => ?COMPLETION_ITEM_KIND_KEYWORD
1167+
}.
1168+
10321169
%%==============================================================================
10331170
%% Built-in functions
10341171
%%==============================================================================

0 commit comments

Comments
 (0)