Skip to content

Commit b726c7e

Browse files
authored
Remove keywords from completions (#259)
* Remove keywords from completions They were being returned regardless of context which made them very noisy. Related: * elixir-lsp/elixir_sense#99 * #251 * Add changelog entry * Return isIncomplete = true for completions * Fix tests and add a couple.
1 parent b79f80d commit b726c7e

File tree

4 files changed

+39
-35
lines changed

4 files changed

+39
-35
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Improvements:
44
- Vendor Jason library to prevent conflicts with user's code (thanks [Jason Axelson](https://github.com/axelson)) [#253](https://github.com/elixir-lsp/elixir-ls/pull/253)
55
- Switch to new supervisor format (thanks [Jason Axelson](https://github.com/axelson)) [#260](https://github.com/elixir-lsp/elixir-ls/pull/260)
66

7+
Changes:
8+
- No longer always return a static list of keywords for completion (thanks [Jason Axelson](https://github.com/axelson)) [#259](https://github.com/elixir-lsp/elixir-ls/pull/259)
9+
710
Bug Fixes:
811
- Formatting was returning invalid floating point number (thanks [Thanabodee Charoenpiriyakij](https://github.com/wingyplus)) [#250](https://github.com/elixir-lsp/elixir-ls/pull/250)
912

apps/language_server/lib/language_server/providers/completion.ex

+12-32
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
7575
"ExUnit.Assertions"
7676
])
7777

78-
@keywords %{
79-
"end" => "end",
80-
"do" => "do\n\t$0\nend",
81-
"true" => "true",
82-
"false" => "false",
83-
"nil" => "nil",
84-
"when" => "when",
85-
"else" => "else\n\t$0",
86-
"rescue" => "rescue\n\t$0",
87-
"catch" => "catch\n\t$0",
88-
"after" => "after\n\t$0"
89-
}
90-
9178
def trigger_characters do
9279
# VS Code's 24x7 autocompletion triggers automatically on alphanumeric characters. We add these
9380
# for "SomeModule." calls and @module_attrs
@@ -148,7 +135,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
148135
ElixirSense.suggestions(text, line + 1, character + 1)
149136
|> Enum.map(&from_completion_item(&1, context, options))
150137
|> Enum.concat(module_attr_snippets(context))
151-
|> Enum.concat(keyword_completions(context))
152138

153139
items_json =
154140
items
@@ -157,11 +143,22 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
157143
|> sort_items()
158144
|> items_to_json(options)
159145

160-
{:ok, %{"isIncomplete" => false, "items" => items_json}}
146+
{:ok, %{"isIncomplete" => is_incomplete(items_json), "items" => items_json}}
161147
end
162148

163149
## Helpers
164150

151+
defp is_incomplete(items) do
152+
if Enum.empty?(items) do
153+
false
154+
else
155+
# By returning isIncomplete = true we tell the client that it should
156+
# always fetch more results, this lets us control the ordering of
157+
# completions accurately
158+
true
159+
end
160+
end
161+
165162
defp from_completion_item(
166163
%{type: :attribute, name: name},
167164
%{
@@ -585,23 +582,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
585582

586583
defp module_attr_snippets(_), do: []
587584

588-
# These aren't really useful, to be honest, and it interferes with the auto-indentation
589-
# for "else", but better to show them even if there's no good reason to use them
590-
defp keyword_completions(%{prefix: prefix}) do
591-
@keywords
592-
|> Enum.filter(fn {keyword, _} -> String.starts_with?(keyword, prefix) end)
593-
|> Enum.map(fn {keyword, snippet} ->
594-
%__MODULE__{
595-
label: keyword,
596-
kind: :keyword,
597-
detail: "keyword",
598-
insert_text: snippet,
599-
tags: [],
600-
priority: 1
601-
}
602-
end)
603-
end
604-
605585
defp function_completion(info, context, options) do
606586
%{
607587
type: type,

apps/language_server/test/providers/completion_test.exs

+22-1
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,34 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do
339339

340340
{line, char} = {4, 14}
341341
TestUtils.assert_has_cursor_char(text, line, char)
342-
{:ok, %{"items" => items}} = Completion.completion(text, line, char, @supports)
342+
{:ok, result} = Completion.completion(text, line, char, @supports)
343+
344+
assert result["isIncomplete"] == true
345+
items = result["items"]
343346

344347
assert ["__struct__", "other", "some"] ==
345348
items |> Enum.filter(&(&1["kind"] == 5)) |> Enum.map(& &1["label"]) |> Enum.sort()
346349

347350
assert (items |> hd)["detail"] == "MyModule struct field"
348351
end
352+
353+
test "isIncomplete is false when there are no results" do
354+
text = """
355+
defmodule MyModule do
356+
defstruct [some: nil, other: 1]
357+
358+
def dummy_function() do
359+
# ^
360+
end
361+
"""
362+
363+
{line, char} = {3, 25}
364+
TestUtils.assert_has_cursor_char(text, line, char)
365+
366+
{:ok, result} = Completion.completion(text, line, char, @supports)
367+
assert result["isIncomplete"] == false
368+
assert result["items"] == []
369+
end
349370
end
350371

351372
describe "function completion" do

apps/language_server/test/server_test.exs

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do
9898
resp = assert_receive(%{"id" => 1}, 1000)
9999

100100
assert response(1, %{
101-
"isIncomplete" => false,
101+
"isIncomplete" => true,
102102
"items" => [
103103
%{
104104
"detail" => "behaviour",
@@ -423,7 +423,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do
423423
resp = assert_receive(%{"id" => 3}, 5000)
424424

425425
assert response(3, %{
426-
"isIncomplete" => false,
426+
"isIncomplete" => true,
427427
"items" => [
428428
%{
429429
"detail" => "module",

0 commit comments

Comments
 (0)